Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0bc0e31
zend_types: Remove `ZEND_RESULT_CODE` typedef (#21850)
TimWolla Apr 23, 2026
d56253c
ext/phar: refactor Phar::__construct() to use zend_string* (#21838)
Girgias Apr 23, 2026
1b1c4ad
ext/phar: refactor Phar::loadPhar() to use a zend_string* (#21837)
Girgias Apr 23, 2026
6c7ef56
ext/phar: refactor phar_build_entry_data() to use a zend_string* for …
Girgias Apr 23, 2026
c23efeb
Zlib: Fix the bug when `zval_get_long` silently cast `$strategy` into…
LamentXU123 Apr 23, 2026
9a530a1
Fix GH-21742: SplFileObject::fgets() throws at EOF in eof/fgets loop …
iliaal Apr 23, 2026
eafc267
zend_compile: Fix incorrect use of `ZVAL_NEW_STR()` in `zend_compile_…
TimWolla Apr 23, 2026
5f989aa
Merge branch 'PHP-8.4' into PHP-8.5
TimWolla Apr 23, 2026
6f1df9e
Merge branch 'PHP-8.5'
TimWolla Apr 23, 2026
20b0ff7
ext/phar: refactor phar_get_or_create_entry_data() to use a zend_stri…
Girgias Apr 23, 2026
aeda891
ext/phar: refactor clean-up code on Windows for phar_open_parsed_phar…
Girgias Apr 23, 2026
11f0288
random: Drop leading `_` from struct names (#21856)
TimWolla Apr 23, 2026
cdc84d9
ext/phar: refactor phar_get_entry_data() to use a zend_string* for fname
Girgias Apr 22, 2026
985cf1e
ext/phar: refactor phar_open_or_create_filename() to use a zend_strin…
Girgias Apr 22, 2026
f435e3a
ext/phar: refactor phar_open_or_create_tar() to use a zend_string* fo…
Girgias Apr 22, 2026
b9be2e2
ext/phar: refactor phar_open_or_create_zip() to use a zend_string* fo…
Girgias Apr 22, 2026
34a9274
ext/phar: refactor phar_create_or_parse_filename() to use a zend_stri…
Girgias Apr 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,8 @@ PHP NEWS
. Added ZipArchive::openString() method.
(Tim Starling, Soner Sayakci, Ghaith Olabi)

- Zlib:
. deflate_init() now raises a TypeError when the value for option
"strategy" is not of type int. (Weilin Du)

<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ PHP 8.6 UPGRADE NOTES
files argument if one or more of the entries is not
a string.

- Zlib:
. deflate_init() now raises a TypeError when the value for option
"strategy" is not of type int.

========================================
2. New Features
========================================
Expand Down
1 change: 1 addition & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ PHP 8.6 INTERNALS UPGRADE NOTES
. Functions using zend_forbid_dynamic_call() *must* be flagged with
ZEND_ACC2_FORBID_DYN_CALLS (@forbid-dynamic-calls in stubs). In debug
builds, failing to include that flag will lead to assertion failures.
. The ZEND_RESULT_CODE type has been removed. Use zend_result directly.

========================
2. Build system changes
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5465,7 +5465,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type)
}

zval_ptr_dtor(&name_node.u.constant);
ZVAL_NEW_STR(&name_node.u.constant, lcname);
ZVAL_STR(&name_node.u.constant, lcname);

opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
opline->result.num = zend_alloc_cache_slot();
Expand Down
6 changes: 2 additions & 4 deletions Zend/zend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,10 @@

typedef unsigned char zend_uchar;

typedef enum {
typedef enum zend_result {
SUCCESS = 0,
FAILURE = -1, /* this MUST stay a negative number, or it may affect functions! */
} ZEND_RESULT_CODE;

typedef ZEND_RESULT_CODE zend_result;
} zend_result;

/* This constant is deprecated, use SIZE_MAX instead */
#define ZEND_SIZE_MAX SIZE_MAX
Expand Down
66 changes: 33 additions & 33 deletions ext/phar/phar.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,15 +504,20 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al
phar_unixify_path_separators(fname, fname_len);
}
#endif
if (SUCCESS == phar_get_archive(&phar, fname, fname_len, alias, alias_len, error)
&& ((alias && zend_string_equals_cstr(phar->fname, fname, fname_len)) || !alias)
) {
zend_result archive_retrieved = phar_get_archive(&phar, fname, fname_len, alias, alias_len, error);
/* logic is as follows:
- If no alias was passed in, then it can match either and be valid
- If an explicit alias was requested, ensure the filename passed in matches the phar's filename.
*/
bool process_phar = SUCCESS == archive_retrieved && (!alias || zend_string_equals_cstr(phar->fname, fname, fname_len));
#ifdef PHP_WIN32
if (fname != save_fname) {
free_alloca(fname, fname_use_heap);
fname = save_fname;
}
if (fname != save_fname) {
free_alloca(fname, fname_use_heap);
fname = save_fname;
}
#endif

if (process_phar) {
/* logic above is as follows:
If an explicit alias was requested, ensure the filename passed in
matches the phar's filename.
Expand All @@ -537,12 +542,6 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al

return SUCCESS;
} else {
#ifdef PHP_WIN32
if (fname != save_fname) {
free_alloca(fname, fname_use_heap);
fname = save_fname;
}
#endif
if (pphar) {
*pphar = NULL;
}
Expand Down Expand Up @@ -1304,7 +1303,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname
/**
* Create or open a phar for writing
*/
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
const char *ext_str, *z;
char *my_error;
Expand All @@ -1316,31 +1315,31 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(ch
*error = NULL;

/* first try to open an existing file */
if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, true) == SUCCESS) {
if (phar_detect_phar_fname_ext(ZSTR_VAL(fname), ZSTR_LEN(fname), &ext_str, &ext_len, !is_data, 0, true) == SUCCESS) {
goto check_file;
}

/* next try to create a new file */
if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, true)) {
if (FAILURE == phar_detect_phar_fname_ext(ZSTR_VAL(fname), ZSTR_LEN(fname), &ext_str, &ext_len, !is_data, 1, true)) {
if (ext_len == -2) {
spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname);
spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", ZSTR_VAL(fname));
} else {
spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", fname);
spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", ZSTR_VAL(fname));
}
return FAILURE;
}
check_file:
if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error) == SUCCESS) {
if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, is_data, options, test, &my_error) == SUCCESS) {
*pphar = *test;

if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) {
spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname);
spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", ZSTR_VAL(fname));
return FAILURE;
}

if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) {
if (!zend_hash_str_exists(&((*test)->manifest), ZEND_STRL(".phar/stub.php"))) {
spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", ZSTR_VAL(fname));
return FAILURE;
}
}
Expand All @@ -1356,40 +1355,40 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(ch

if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) {
/* assume zip-based phar */
return phar_open_or_create_zip(fname, fname_len, alias, alias_len, is_data, options, pphar, error);
return phar_open_or_create_zip(fname, alias, alias_len, is_data, options, pphar, error);
}

if (ext_len > 3 && (z = memchr(ext_str, 't', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ar", 2)) {
/* assume tar-based phar */
return phar_open_or_create_tar(fname, fname_len, alias, alias_len, is_data, options, pphar, error);
return phar_open_or_create_tar(fname, alias, alias_len, is_data, options, pphar, error);
}

return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, pphar, error);
return phar_create_or_parse_filename(fname, alias, alias_len, is_data, options, pphar, error);
}
/* }}} */

static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error);

ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
php_stream *fp;
zend_string *actual = NULL;
zend_string *save_fname = fname;
char *p;

if (php_check_open_basedir(fname)) {
if (php_check_open_basedir(ZSTR_VAL(fname))) {
return FAILURE;
}

/* first open readonly so it won't be created if not present */
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual);
fp = php_stream_open_wrapper(ZSTR_VAL(fname), "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual);

if (actual) {
fname = ZSTR_VAL(actual);
fname_len = ZSTR_LEN(actual);
fname = actual;
}

if (fp) {
if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error) == SUCCESS) {
if (phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, options, pphar, error) == SUCCESS) {
if ((*pphar)->is_data || !PHAR_G(readonly)) {
(*pphar)->is_writeable = 1;
}
Expand All @@ -1408,19 +1407,20 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c

if (actual) {
zend_string_release_ex(actual, 0);
fname = save_fname;
}

if (PHAR_G(readonly) && !is_data) {
if (options & REPORT_ERRORS) {
spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", fname);
spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", ZSTR_VAL(fname));
}
return FAILURE;
}

/* set up our manifest */
phar_archive_data *mydata = ecalloc(1, sizeof(phar_archive_data));
/* TODO: prevent reallocation via a new expand_filepath() API? */
char *new_fname = expand_filepath(fname, NULL);
char *new_fname = expand_filepath(ZSTR_VAL(fname), NULL);
if (new_fname == NULL) {
efree(mydata);
return FAILURE;
Expand Down Expand Up @@ -1485,7 +1485,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c
if (alias_len && alias) {
if (NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata)) {
if (options & REPORT_ERRORS) {
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias);
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", ZSTR_VAL(fname), alias);
}

zend_hash_del(&(PHAR_G(phar_fname_map)), mydata->fname);
Expand Down
12 changes: 6 additions & 6 deletions ext/phar/phar_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ void phar_destroy_phar_data(phar_archive_data *phar);

ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip);
zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error);
zend_result phar_free_alias(const phar_archive_data *phar);
zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error);
Expand Down Expand Up @@ -446,12 +446,12 @@ zend_result phar_copy_on_write(phar_archive_data **pphar);
/* tar functions in tar.c */
bool phar_is_tar(const char *buf, const char *fname);
zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error);

/* zip functions in zip.c */
zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error);

#ifdef PHAR_MAIN
Expand All @@ -466,8 +466,8 @@ void phar_entry_delref(phar_entry_data *idata);

phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, bool security);
phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, bool security);
ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp);
ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security);
ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp);
ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error);
ZEND_ATTRIBUTE_NONNULL int phar_flush(phar_archive_data *archive, char **error);
zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete);
Expand Down
Loading
Loading