From 5c1194d99102b45cbcdd8e2e6c6ad647d4f946b7 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Fri, 17 Apr 2026 13:31:32 +0530 Subject: [PATCH 01/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/zip.c | 74 ++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index f757adc90c88..9179bd0e9995 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -232,9 +232,9 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l uint16_t i; phar_archive_data *mydata = NULL; phar_entry_info entry = {0}; - char *ext, *actual_alias = NULL; + char *ext = NULL; char *metadata = NULL; - + zend_string *actual_alias = NULL; size = php_stream_tell(fp); if (size > sizeof(locator) + 65536) { @@ -341,7 +341,10 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l entry.fp_type = PHAR_FP; entry.is_persistent = mydata->is_persistent; #define PHAR_ZIP_FAIL(errmsg) \ - efree(actual_alias); \ + if (actual_alias) { \ + zend_string_release_ex(actual_alias, 0); \ + actual_alias = NULL; \ + } \ zend_hash_destroy(&mydata->manifest); \ HT_INVALIDATE(&mydata->manifest); \ zend_hash_destroy(&mydata->mounted_dirs); \ @@ -600,7 +603,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l ZVAL_UNDEF(&entry.metadata_tracker.val); } - if (!actual_alias && zend_string_equals_literal(entry.filename, ".phar/alias.txt")) { + if (actual_alias == NULL && zend_string_equals_literal(entry.filename, ".phar/alias.txt")) { php_stream_filter *filter; /* archive alias found */ @@ -626,19 +629,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); - // TODO: refactor to avoid reallocation ??? -//??? entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0) - { - zend_string *str = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - if (str) { - entry.uncompressed_filesize = ZSTR_LEN(str); - actual_alias = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_string_release_ex(str, 0); - } else { - actual_alias = NULL; - entry.uncompressed_filesize = 0; - } - } + actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); @@ -658,20 +649,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l } php_stream_filter_append(&fp->readfilters, filter); - - // TODO: refactor to avoid reallocation ??? -//??? entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0) - { - zend_string *str = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - if (str) { - entry.uncompressed_filesize = ZSTR_LEN(str); - actual_alias = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_string_release_ex(str, 0); - } else { - actual_alias = NULL; - entry.uncompressed_filesize = 0; - } - } + actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); @@ -682,19 +660,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1); } else { - // TODO: refactor to avoid reallocation ??? -//??? entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0) - { - zend_string *str = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - if (str) { - entry.uncompressed_filesize = ZSTR_LEN(str); - actual_alias = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_string_release_ex(str, 0); - } else { - actual_alias = NULL; - entry.uncompressed_filesize = 0; - } - } + actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); if (!entry.uncompressed_filesize) { zend_string_release_ex(entry.filename, entry.is_persistent); @@ -725,37 +691,37 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l zend_hash_str_add_ptr(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len, mydata); - if (actual_alias) { + if (actual_alias != NULL) { phar_archive_data *fd_ptr; - if (!phar_validate_alias(actual_alias, mydata->alias_len)) { + if (!phar_validate_alias(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias))) { if (error) { - spprintf(error, 4096, "phar error: invalid alias \"%s\" in zip-based phar \"%s\"", actual_alias, fname); + spprintf(error, 4096, "phar error: invalid alias \"%s\" in zip-based phar \"%s\"", ZSTR_VAL(actual_alias), fname); } - efree(actual_alias); + zend_string_release_ex(actual_alias, 0); zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len); return FAILURE; } mydata->is_temporary_alias = 0; - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), actual_alias, mydata->alias_len))) { + if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias)))) { if (SUCCESS != phar_free_alias(fd_ptr)) { if (error) { spprintf(error, 4096, "phar error: Unable to add zip-based phar \"%s\" with implicit alias, alias is already in use", fname); } - efree(actual_alias); + zend_string_release_ex(actual_alias, 0); zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len); return FAILURE; } } - mydata->alias = entry.is_persistent ? pestrndup(actual_alias, mydata->alias_len, 1) : actual_alias; - if (entry.is_persistent) { - efree(actual_alias); + mydata->alias = pestrndup(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias), 1); + } else { + mydata->alias = estrndup(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias)); } - + zend_string_release_ex(actual_alias, 0); zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), mydata->alias, mydata->alias_len, mydata); } else { phar_archive_data *fd_ptr; From 98b160143c62269f348e35f78c98549d9b93abe4 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Fri, 17 Apr 2026 13:46:20 +0530 Subject: [PATCH 02/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/zip.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 9179bd0e9995..771866be950d 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -630,8 +630,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - - if (!entry.uncompressed_filesize) { + if (!actual_alias || !entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -650,8 +649,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - - if (!entry.uncompressed_filesize) { + if (!actual_alias || !entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -661,8 +659,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_remove(filter, 1); } else { actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - - if (!entry.uncompressed_filesize) { + if (!actual_alias || !entry.uncompressed_filesize) { zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); } From b41aa38ec6687dcdf4540f64d43f56752b82b8c3 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Fri, 17 Apr 2026 13:47:29 +0530 Subject: [PATCH 03/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/zip.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 771866be950d..67e8aafdeb42 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -630,7 +630,8 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - if (!actual_alias || !entry.uncompressed_filesize) { + entry.uncompressed_filesize = ZSTR_LEN(actual_alias); + if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -649,7 +650,8 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - if (!actual_alias || !entry.uncompressed_filesize) { + entry.uncompressed_filesize = ZSTR_LEN(actual_alias); + if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -659,7 +661,8 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_remove(filter, 1); } else { actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - if (!actual_alias || !entry.uncompressed_filesize) { + entry.uncompressed_filesize = ZSTR_LEN(actual_alias); + if (!entry.uncompressed_filesize) { zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); } From 8b9558e550a0a2488187779e299c79d09cbce740 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Fri, 17 Apr 2026 17:46:51 +0530 Subject: [PATCH 04/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/zip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 67e8aafdeb42..5509b7582f43 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -603,7 +603,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l ZVAL_UNDEF(&entry.metadata_tracker.val); } - if (actual_alias == NULL && zend_string_equals_literal(entry.filename, ".phar/alias.txt")) { + if (!actual_alias && zend_string_equals_literal(entry.filename, ".phar/alias.txt")) { php_stream_filter *filter; /* archive alias found */ @@ -705,7 +705,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l mydata->is_temporary_alias = 0; - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias)))) { + if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias)))) { if (SUCCESS != phar_free_alias(fd_ptr)) { if (error) { spprintf(error, 4096, "phar error: Unable to add zip-based phar \"%s\" with implicit alias, alias is already in use", fname); From 33f5cb723e67c41603d8c6e4ce41b73ff02f93f3 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 18 Apr 2026 15:37:07 +0530 Subject: [PATCH 05/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/dirstream.c | 10 +-- ext/phar/func_interceptors.c | 8 +-- ext/phar/phar.c | 122 ++++++++++++++++++----------------- ext/phar/phar_internal.h | 23 ++++--- ext/phar/phar_object.c | 91 ++++++++++++++------------ ext/phar/stream.c | 14 ++-- ext/phar/tar.c | 99 ++++++++++++++++++++++------ ext/phar/util.c | 63 ++++++++---------- ext/phar/zip.c | 57 ++++++++-------- 9 files changed, 273 insertions(+), 214 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index c486fd41abfd..eec15f8708e1 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -276,7 +276,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, phar_request_initialize(); - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, &error)) { if (error) { php_stream_wrapper_log_error(wrapper, options, "%s", error); efree(error); @@ -355,7 +355,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) { phar = NULL; } @@ -383,7 +383,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, &error)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path) + 1, ZSTR_VAL(resource->host), error); efree(error); php_url_free(resource); @@ -481,7 +481,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) { phar = NULL; } @@ -509,7 +509,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, &error)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error); efree(error); php_url_free(resource); diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index 0e7d2df0db61..97f30fb3aefd 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -101,7 +101,7 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file defaults to within the current directory, so use this if possible */ phar_archive_data *phar; - if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) { efree(arch); return NULL; } @@ -496,7 +496,7 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ size_t arch_len; if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) { /* fopen within phar, if :// is not in the url, then prepend phar:/// */ - zend_result has_archive = phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL); + zend_result has_archive = phar_get_archive(&phar, arch, arch_len, NULL, NULL); efree(arch); if (FAILURE == has_archive) { goto skip_phar; @@ -736,7 +736,7 @@ PHP_FUNCTION(phar_is_file) /* {{{ */ /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file within the current directory, so use this if possible */ - if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { + if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) { phar_entry_info *etemp; zend_string *entry = phar_fix_filepath(filename, filename_len, true); @@ -794,7 +794,7 @@ PHP_FUNCTION(phar_is_link) /* {{{ */ /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file within the current directory, so use this if possible */ - if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { + if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) { phar_entry_info *etemp; zend_string *entry = phar_fix_filepath(filename, filename_len, true); diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 5fb6c864be74..9caa8923e526 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -131,7 +131,7 @@ static void phar_split_cache_list(void) /* {{{ */ len = strlen(key); } - if (SUCCESS == phar_open_from_filename(key, len, NULL, 0, 0, &phar, NULL)) { + if (SUCCESS == phar_open_from_filename(key, len, NULL, 0, &phar, NULL)) { phar->phar_pos = i++; php_stream_close(phar->fp); phar->fp = NULL; @@ -192,8 +192,8 @@ PHP_INI_END() */ void phar_destroy_phar_data(phar_archive_data *phar) /* {{{ */ { - if (phar->alias && phar->alias != phar->fname) { - pefree(phar->alias, phar->is_persistent); + if (phar->alias) { + zend_string_release_ex(phar->alias, phar->is_persistent); phar->alias = NULL; } @@ -460,6 +460,9 @@ ZEND_ATTRIBUTE_NONNULL void phar_entry_remove(phar_entry_data *idata, char **err if (signature) {\ pefree(signature, PHAR_G(persist));\ }\ + if (alias) { \ + zend_string_release_ex(alias, 0); \ + }\ MAPPHAR_ALLOC_FAIL(msg) #ifdef WORDS_BIGENDIAN @@ -484,7 +487,7 @@ ZEND_ATTRIBUTE_NONNULL void phar_entry_remove(phar_entry_data *idata, char **err /** * Open an already loaded phar */ -static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; #ifdef PHP_WIN32 @@ -504,7 +507,7 @@ 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) + if (SUCCESS == phar_get_archive(&phar, fname, fname_len, alias, error) && ((alias && fname_len == phar->fname_len && !strncmp(fname, phar->fname, fname_len)) || !alias) ) { @@ -723,7 +726,7 @@ void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker * This is used by phar_open_from_filename to process the manifest, but can be called * directly. */ -static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, zend_long halt_offset, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ +static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, zend_string *alias, zend_long halt_offset, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ { char b32[4], *buffer, *endbuffer, *savebuf; phar_archive_data *mydata = NULL; @@ -1047,7 +1050,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /* tmp_len = 0 says alias length is 0, which means the alias is not stored in the phar */ if (tmp_len) { /* if the alias is stored we enforce it (implicit overrides explicit) */ - if (alias && alias_len && (alias_len != tmp_len || strncmp(alias, buffer, tmp_len))) + if (alias && (ZSTR_LEN(alias) != tmp_len || strncmp(ZSTR_VAL(alias), buffer, tmp_len))) { php_stream_close(fp); @@ -1056,23 +1059,21 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname } if (error) { - spprintf(error, 0, "cannot load phar \"%s\" with implicit alias \"%.*s\" under different alias \"%s\"", fname, tmp_len, buffer, alias); + spprintf(error, 0, "cannot load phar \"%s\" with implicit alias \"%.*s\" under different alias \"%s\"", fname, tmp_len, buffer, ZSTR_VAL(alias)); } efree(savebuf); return FAILURE; } - alias_len = tmp_len; - alias = buffer; + alias = zend_string_init(buffer, tmp_len, 0); buffer += tmp_len; register_alias = true; - } else if (!alias_len || !alias) { + } else if (!alias) { /* if we neither have an explicit nor an implicit alias, we use the filename */ alias = NULL; - alias_len = 0; register_alias = false; - } else if (alias_len) { + } else if (ZSTR_LEN(alias)) { register_alias = true; temp_alias = true; } @@ -1242,10 +1243,14 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname } } - mydata->alias = alias ? - pestrndup(alias, alias_len, mydata->is_persistent) : - pestrndup(mydata->fname, fname_len, mydata->is_persistent); - mydata->alias_len = alias ? alias_len : fname_len; + if (alias) { + mydata->alias = zend_string_init(ZSTR_VAL(alias), ZSTR_LEN(alias), mydata->is_persistent); + } else { + mydata->alias = zend_string_init(mydata->fname, fname_len, mydata->is_persistent); + } + if (mydata->is_persistent) { + GC_MAKE_PERSISTENT_LOCAL(mydata->alias); + } mydata->sig_flags = sig_flags; mydata->fp = fp; mydata->sig_len = sig_len; @@ -1257,13 +1262,13 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname mydata->is_temporary_alias = temp_alias; - if (!phar_validate_alias(mydata->alias, mydata->alias_len)) { + if (!phar_validate_alias(ZSTR_VAL(mydata->alias), ZSTR_LEN(mydata->alias))) { signature = NULL; fp = NULL; MAPPHAR_FAIL("Cannot open archive \"%s\", invalid alias"); } - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias))) { if (SUCCESS != phar_free_alias(fd_ptr)) { signature = NULL; fp = NULL; @@ -1272,9 +1277,9 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname } if (mydata->is_persistent) { - str = zend_string_init_interned(alias, alias_len, 1); + str = zend_string_init_interned(ZSTR_VAL(alias), ZSTR_LEN(alias), 1); } else { - str = zend_string_init(alias, alias_len, 0); + str = zend_string_init(ZSTR_VAL(alias), ZSTR_LEN(alias), 0); } zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), str, mydata); zend_string_release(str); @@ -1291,6 +1296,10 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname zend_string_release(str); efree(savebuf); + if(alias){ + zend_string_release_ex(alias, 0); + } + if (pphar) { *pphar = mydata; } @@ -1302,7 +1311,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(char *fname, size_t fname_len, zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { const char *ext_str, *z; char *my_error; @@ -1328,7 +1337,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(ch 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(fname, fname_len, alias, is_data, options, test, &my_error) == SUCCESS) { *pphar = *test; if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) { @@ -1354,21 +1363,21 @@ 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, fname_len, alias, 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, fname_len, alias, 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, fname_len, alias, 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); +static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, zend_string *alias, 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(char *fname, size_t fname_len, zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual = NULL; @@ -1387,7 +1396,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c } if (fp) { - if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error) == SUCCESS) { + if (phar_open_from_fp(fp, fname, fname_len, alias, options, pphar, error) == SUCCESS) { if ((*pphar)->is_data || !PHAR_G(readonly)) { (*pphar)->is_writeable = 1; } @@ -1455,16 +1464,15 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c if (is_data) { alias = NULL; - alias_len = 0; mydata->is_data = 1; /* assume tar format, PharData can specify other */ mydata->is_tar = 1; } else { phar_archive_data *fd_ptr; - if (alias && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { + if (alias && NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias))) { if (SUCCESS != phar_free_alias(fd_ptr)) { - spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias); + spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, ZSTR_VAL(alias)); zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len); @@ -1475,14 +1483,13 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c } ZEND_ASSERT(!mydata->is_persistent); - mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len); - mydata->alias_len = alias ? alias_len : fname_len; + mydata->alias = alias ? alias : zend_string_init(mydata->fname, fname_len, false); } - if (alias_len && alias) { - if (NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata)) { + if (alias) { + if (NULL == zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), alias, 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", fname, ZSTR_VAL(alias)); } zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len); @@ -1505,7 +1512,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -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_result phar_open_from_filename(char *fname, size_t fname_len, zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual; @@ -1519,7 +1526,7 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, is_data = true; } - if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, pphar, error) == SUCCESS) { + if (phar_open_parsed_phar(fname, fname_len, alias, is_data, options, pphar, error) == SUCCESS) { return SUCCESS; } else if (error && *error) { return FAILURE; @@ -1547,7 +1554,7 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, fname_len = ZSTR_LEN(actual); } - zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error); + zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias, options, pphar, error); if (actual) { zend_string_release_ex(actual, 0); @@ -1562,7 +1569,7 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -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) /* {{{ */ +static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { static const char token[] = "__HALT_COMPILER();"; static const char zip_magic[] = "PK\x03\x04"; @@ -1714,20 +1721,20 @@ static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_l if (!memcmp(pos, zip_magic, 4)) { php_stream_seek(fp, 0, SEEK_END); - return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error); + return phar_parse_zipfile(fp, fname, fname_len, alias, pphar, error); } if (got >= 512) { if (phar_is_tar(pos, fname)) { php_stream_rewind(fp); - return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, compression, error); + return phar_parse_tarfile(fp, fname, fname_len, alias, pphar, compression, error); } } } if (got > 0 && (pos = php_memnistr(buffer, token, tokenlen, buffer + got + sizeof(token))) != NULL) { halt_offset += (pos - buffer); /* no -tokenlen+tokenlen here */ - return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error); + return phar_parse_pharfile(fp, fname, fname_len, alias, halt_offset, pphar, compression, error); } halt_offset += got; @@ -2240,7 +2247,7 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a * Invoked when a user calls Phar::mapPhar() from within an executing .phar * to set up its manifest directly */ -ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(zend_string *alias, char **error) /* {{{ */ { *error = NULL; @@ -2251,7 +2258,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *ali return FAILURE; } - if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, false, REPORT_ERRORS, NULL, NULL) == SUCCESS) { + if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, false, REPORT_ERRORS, NULL, NULL) == SUCCESS) { return SUCCESS; } @@ -2280,7 +2287,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *ali fname = actual; } - zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, REPORT_ERRORS, NULL, error); + zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, REPORT_ERRORS, NULL, error); if (actual) { zend_string_release_ex(actual, 0); @@ -2463,7 +2470,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen phar_entry_info *entry, *newentry; size_t halt_offset; - uint32_t restore_alias_len; uint32_t global_flags = 0; bool must_close_old_file = false; bool has_dirs = false; @@ -2758,12 +2764,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen * 4: phar metadata length * ?: phar metadata */ - restore_alias_len = phar->alias_len; - if (phar->is_temporary_alias) { - phar->alias_len = 0; + size_t written_alias_len; + if (phar->is_temporary_alias || !phar->alias) { + written_alias_len = 0; + } else { + written_alias_len = ZSTR_LEN(phar->alias); } - manifest_len = offset + phar->alias_len + sizeof(manifest) + (main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0); + manifest_len = offset + written_alias_len + sizeof(manifest) + (main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0); phar_set_32(manifest, manifest_len); /* Hack - see bug #65028, add padding byte to the end of the manifest */ if(manifest[0] == '\r' || manifest[0] == '\n') { @@ -2780,25 +2788,22 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION_NODIR) & 0xF0)); } phar_set_32(manifest+10, global_flags); - phar_set_32(manifest+14, phar->alias_len); + phar_set_32(manifest+14, written_alias_len); /* write the manifest header */ if (sizeof(manifest) != php_stream_write(newfile, manifest, sizeof(manifest)) - || (size_t)phar->alias_len != php_stream_write(newfile, phar->alias, phar->alias_len)) { - + || (written_alias_len > 0 && written_alias_len != php_stream_write(newfile, ZSTR_VAL(phar->alias), written_alias_len))) { if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - phar->alias_len = restore_alias_len; spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname); goto cleanup; } - phar->alias_len = restore_alias_len; phar_set_32(manifest, main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0); if (4 != php_stream_write(newfile, manifest, 4) || ((main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0) @@ -2810,7 +2815,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen } php_stream_close(newfile); - phar->alias_len = restore_alias_len; spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname); @@ -3149,7 +3153,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) return phar_orig_compile_file(file_handle, type); } if (strstr(ZSTR_VAL(file_handle->filename), ".phar") && !strstr(ZSTR_VAL(file_handle->filename), "://")) { - if (SUCCESS == phar_open_from_filename(ZSTR_VAL(file_handle->filename), ZSTR_LEN(file_handle->filename), NULL, 0, 0, &phar, NULL)) { + if (SUCCESS == phar_open_from_filename(ZSTR_VAL(file_handle->filename), ZSTR_LEN(file_handle->filename), NULL, 0, &phar, NULL)) { if (phar->is_zip || phar->is_tar) { zend_file_handle f; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index a60c5ed5d432..bb290a03c5aa 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -149,7 +149,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) char* last_phar_name; uint32_t last_phar_name_len; uint32_t last_alias_len; - const char* last_alias; + zend_string* last_alias; phar_archive_data* last_phar; HashTable mime_types; ZEND_END_MODULE_GLOBALS(phar) @@ -248,8 +248,7 @@ struct _phar_archive_data { /* for phar_detect_fname_ext, this stores the location of the file extension within fname */ uint32_t ext_len; char *ext; - char *alias; - uint32_t alias_len; + zend_string *alias; char version[12]; size_t halt_offset; HashTable manifest; @@ -409,12 +408,12 @@ void phar_object_init(void); 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(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); +zend_result phar_open_from_filename(char *fname, size_t fname_len, zend_string *alias,uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(char *fname, size_t fname_len, zend_string *alias, 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(char *fname, size_t fname_len, zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(zend_string *alias, 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); +zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, zend_string *alias, char **error); zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error); @@ -448,13 +447,13 @@ 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_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, zend_string *alias, phar_archive_data** pphar, uint32_t compression, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(char *fname, size_t fname_len, zend_string *alias, 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_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, zend_string *alias, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(char *fname, size_t fname_len, zend_string *alias, 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 diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index f97240010d48..996586cbdbc8 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -550,8 +550,8 @@ PHP_METHOD(Phar, webPhar) zval *mimeoverride = NULL; zend_fcall_info rewrite_fci = {0}; zend_fcall_info_cache rewrite_fcc; - char *alias = NULL, *error, *index_php = NULL, *ru = NULL; - size_t alias_len = 0, free_pathinfo = 0; + char *error, *index_php = NULL, *ru = NULL; + size_t free_pathinfo = 0; zend_string *f404 = NULL; size_t ru_len = 0; char *fname, *path_info, *mime_type = NULL, *entry, *pt; @@ -563,14 +563,15 @@ PHP_METHOD(Phar, webPhar) phar_entry_info *info = NULL; size_t sapi_mod_name_len = strlen(sapi_module.name); phar_action_status status = PHAR_ACT_DO_EXIT; + zend_string *alias = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!S!af!", &alias, &alias_len, &index_php, &index_php_len, &f404, &mimeoverride, &rewrite_fci, &rewrite_fcc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!s!S!af!", &alias, &index_php, &index_php_len, &f404, &mimeoverride, &rewrite_fci, &rewrite_fcc) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - if (phar_open_executed_filename(alias, alias_len, &error) != SUCCESS) { + if (phar_open_executed_filename(alias, &error) != SUCCESS) { if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); efree(error); @@ -748,7 +749,7 @@ PHP_METHOD(Phar, webPhar) entry_len = sizeof("/index.php")-1; } - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) || + if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, NULL) || (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { phar_do_404(phar, fname, fname_len, f404); } else { @@ -789,7 +790,7 @@ PHP_METHOD(Phar, webPhar) goto cleanup_skip_entry; } - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) || + if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, NULL) || (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { phar_do_404(phar, fname, fname_len, f404); goto cleanup; @@ -942,17 +943,17 @@ PHP_METHOD(Phar, createDefaultStub) /* {{{ Reads the currently executed file (a phar) and registers its manifest */ PHP_METHOD(Phar, mapPhar) { - char *alias = NULL, *error; - size_t alias_len = 0; + char *error; + zend_string *alias = NULL; zend_long dataoffset = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!l", &alias, &dataoffset) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error) == SUCCESS); + RETVAL_BOOL(phar_open_executed_filename(alias, &error) == SUCCESS); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); @@ -963,16 +964,17 @@ PHP_METHOD(Phar, mapPhar) /* {{{ Loads any phar archive with an alias */ PHP_METHOD(Phar, loadPhar) { - char *fname, *alias = NULL, *error; - size_t fname_len, alias_len = 0; + char *fname, *error; + size_t fname_len = 0; + zend_string *alias = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!", &fname, &fname_len, &alias, &alias_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|S", &fname, &fname_len, &alias) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS); + RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, REPORT_ERRORS, NULL, &error) == SUCCESS); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); @@ -1077,8 +1079,8 @@ static const spl_other_handler phar_spl_foreign_handler = { */ PHP_METHOD(Phar, __construct) { - char *fname, *alias = NULL, *error, *arch = NULL, *save_fname; - size_t fname_len, alias_len = 0; + char *fname, *error, *arch = NULL, *save_fname; + size_t fname_len; size_t arch_len; bool is_data; zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS; @@ -1086,17 +1088,18 @@ PHP_METHOD(Phar, __construct) phar_archive_object *phar_obj; phar_archive_data *phar_data; zval arg1, arg2; + zend_string *alias = NULL; phar_obj = PHAR_FETCH_INTERNAL(); is_data = instanceof_function(Z_OBJCE_P(ZEND_THIS), phar_ce_data); if (is_data) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lS!l", &fname, &fname_len, &flags, &alias, &format) == FAILURE) { RETURN_THROWS(); } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lS!", &fname, &fname_len, &flags, &alias) == FAILURE) { RETURN_THROWS(); } } @@ -1125,7 +1128,7 @@ PHP_METHOD(Phar, __construct) #endif } - if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error) == FAILURE) { + if (phar_open_or_create_filename(fname, fname_len, alias, is_data, REPORT_ERRORS, &phar_data, &error) == FAILURE) { if (fname == arch && fname != save_fname) { efree(arch); @@ -1274,7 +1277,7 @@ PHP_METHOD(Phar, unlinkArchive) RETURN_THROWS(); } - if (FAILURE == phar_open_from_filename(fname, fname_len, NULL, 0, REPORT_ERRORS, &phar, &error)) { + if (FAILURE == phar_open_from_filename(fname, fname_len, NULL, REPORT_ERRORS, &phar, &error)) { if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\": %s", fname, error); efree(error); @@ -2142,12 +2145,13 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* if (phar->alias && phar != pphar) { if (phar->is_temporary_alias) { phar->alias = NULL; - phar->alias_len = 0; } else { - phar->alias = pestrndup(newpath, strlen(newpath), phar->is_persistent); - phar->alias_len = strlen(newpath); + phar->alias = zend_string_init(newpath, strlen(newpath), phar->is_persistent); phar->is_temporary_alias = 1; zend_hash_str_update_ptr(&(PHAR_G(phar_alias_map)), newpath, phar->fname_len, phar); + if(phar->is_persistent){ + GC_MAKE_PERSISTENT_LOCAL(phar->alias); + } } } @@ -2162,7 +2166,6 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* /* See comment in other branch. */ if (phar != pphar) { phar->alias = NULL; - phar->alias_len = 0; } } @@ -2648,8 +2651,11 @@ PHP_METHOD(Phar, getAlias) PHAR_ARCHIVE_OBJECT(); - if (phar_obj->archive->alias && phar_obj->archive->alias != phar_obj->archive->fname) { - RETURN_STRINGL(phar_obj->archive->alias, phar_obj->archive->alias_len); + if (phar_obj->archive->alias) { + if (GC_FLAGS(phar_obj->archive->alias) & GC_PERSISTENT) { + RETURN_STR(zend_string_dup(phar_obj->archive->alias, false)); + } + RETURN_STR_COPY(phar_obj->archive->alias); } } /* }}} */ @@ -2670,10 +2676,9 @@ PHP_METHOD(Phar, getPath) */ PHP_METHOD(Phar, setAlias) { - zend_string *new_alias = NULL; - char *error, *oldalias; + zend_string *new_alias = NULL, *oldalias = NULL; + char *error; phar_archive_data *fd_ptr; - size_t oldalias_len; bool old_temp, readd = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &new_alias) == FAILURE) { @@ -2704,7 +2709,7 @@ PHP_METHOD(Phar, setAlias) RETURN_THROWS(); } - if (zend_string_equals_cstr(new_alias, phar_obj->archive->alias, phar_obj->archive->alias_len)) { + if (phar_obj->archive->alias && zend_string_equals(new_alias, phar_obj->archive->alias)) { RETURN_TRUE; } if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), new_alias))) { @@ -2721,20 +2726,24 @@ PHP_METHOD(Phar, setAlias) zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname); RETURN_THROWS(); } - if (phar_obj->archive->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len))) { - zend_hash_str_del(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len); + if (phar_obj->archive->alias && zend_hash_del(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias) == SUCCESS) { readd = true; } ZEND_ASSERT(!phar_obj->archive->is_persistent); oldalias = phar_obj->archive->alias; - oldalias_len = phar_obj->archive->alias_len; old_temp = phar_obj->archive->is_temporary_alias; - phar_obj->archive->alias_len = ZSTR_LEN(new_alias); - if (phar_obj->archive->alias_len) { - phar_obj->archive->alias = estrndup(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias)); + if (ZSTR_LEN(new_alias)) { + if (phar_obj->archive->is_persistent) { + phar_obj->archive->alias = zend_string_init(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias), phar_obj->archive->is_persistent); + if(phar_obj->archive->is_persistent){ + GC_MAKE_PERSISTENT_LOCAL(phar_obj->archive->alias); + } + } else { + phar_obj->archive->alias = zend_string_copy(new_alias); + } } else { phar_obj->archive->alias = NULL; } @@ -2743,13 +2752,12 @@ PHP_METHOD(Phar, setAlias) phar_flush(phar_obj->archive, &error); if (error) { - efree(phar_obj->archive->alias); + zend_string_release_ex(phar_obj->archive->alias, 0); phar_obj->archive->alias = oldalias; - phar_obj->archive->alias_len = oldalias_len; phar_obj->archive->is_temporary_alias = old_temp; zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); if (readd) { - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), oldalias, oldalias_len, phar_obj->archive); + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), oldalias, phar_obj->archive); } efree(error); RETURN_THROWS(); @@ -2758,7 +2766,7 @@ PHP_METHOD(Phar, setAlias) zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), new_alias, phar_obj->archive); if (oldalias) { - efree(oldalias); + zend_string_release_ex(oldalias, 0); } RETURN_TRUE; @@ -4420,7 +4428,7 @@ PHP_METHOD(PharFileInfo, __construct) RETURN_THROWS(); } - if (phar_open_from_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data, &error) == FAILURE) { + if (phar_open_from_filename(arch, arch_len, NULL, REPORT_ERRORS, &phar_data, &error) == FAILURE) { efree(arch); efree(entry); if (error) { @@ -4459,6 +4467,7 @@ PHP_METHOD(PharFileInfo, __construct) zend_call_known_instance_method_with_1_params(spl_ce_SplFileInfo->constructor, Z_OBJ_P(ZEND_THIS), NULL, &arg1); + zval_ptr_dtor(&arg1); } /* }}} */ diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 4b49703b4abe..ce8da3f24bdb 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -114,7 +114,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const php_url_free(resource); return NULL; } - if (phar_open_or_create_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, 0, options, &phar, &error) == FAILURE) + if (phar_open_or_create_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, options, &phar, &error) == FAILURE) { if (error) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { @@ -137,7 +137,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const return NULL; } } else { - if (phar_open_from_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, options, NULL, &error) == FAILURE) + if (phar_open_from_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, options, NULL, &error) == FAILURE) { if (error) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { @@ -233,7 +233,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } else { if (!*internal_file && (options & STREAM_OPEN_FOR_INCLUDE)) { /* retrieve the stub */ - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, NULL)) { php_stream_wrapper_log_error(wrapper, options, "file %s is not a valid phar archive", ZSTR_VAL(resource->host)); efree(internal_file); php_url_free(resource); @@ -581,7 +581,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f internal_file = ZSTR_VAL(resource->path) + 1; /* strip leading "/" */ /* find the phar in our trusty global hash indexed by alias (host of phar://blah.phar/file.whatever) */ - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, NULL)) { php_url_free(resource); return FAILURE; } @@ -741,7 +741,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_from); return 0; } - if (SUCCESS != phar_get_archive(&pfrom, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, &error)) { + if (SUCCESS != phar_get_archive(&pfrom, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, &error)) { pfrom = NULL; if (error) { efree(error); @@ -758,7 +758,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_to); return 0; } - if (SUCCESS != phar_get_archive(&pto, ZSTR_VAL(resource_to->host), ZSTR_LEN(resource_to->host), NULL, 0, &error)) { + if (SUCCESS != phar_get_archive(&pto, ZSTR_VAL(resource_to->host), ZSTR_LEN(resource_to->host), NULL, &error)) { if (error) { efree(error); } @@ -807,7 +807,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from return 0; } - if (SUCCESS != phar_get_archive(&phar, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, &error)) { + if (SUCCESS != phar_get_archive(&phar, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, &error)) { php_url_free(resource_from); php_url_free(resource_to); php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index ef356bfc7a28..5c1f9ac9b966 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -126,10 +126,10 @@ bool phar_is_tar(const char *buf, const char *fname) /* {{{ */ } /* }}} */ -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(char *fname, size_t fname_len, zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; - zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); + zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, is_data, options, &phar, error); if (FAILURE == ret) { return FAILURE; @@ -197,9 +197,9 @@ static zend_result phar_tar_process_metadata(phar_entry_info *entry, php_stream } /* }}} */ -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_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, zend_string *alias, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ { - char buf[512], *actual_alias = NULL, *p; + char buf[512], *p; phar_entry_info entry = {0}; size_t pos = 0, read, totalsize; tar_header *hdr; @@ -207,6 +207,7 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l phar_archive_data *myphar, *actual; bool last_was_longlink = false; size_t linkname_len; + zend_string *actual_alias = NULL; if (error) { *error = NULL; @@ -285,6 +286,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l } bail: php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -325,6 +329,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -337,6 +344,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -365,6 +375,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (invalid entry size)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -381,6 +394,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -396,6 +412,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -408,6 +427,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -470,6 +492,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l } zend_string_release_ex(entry.filename, myphar->is_persistent); php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -503,6 +528,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l } zend_string_release_ex(entry.filename, myphar->is_persistent); php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -525,6 +553,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: tar-based phar \"%s\" has invalid metadata in magic file \"%s\"", fname, ZSTR_VAL(entry.filename)); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -537,6 +568,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: tar-based phar \"%s\" has alias that is larger than 511 bytes, cannot process", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -558,20 +592,26 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } - actual_alias = pestrndup(buf, size, myphar->is_persistent); - myphar->alias = actual_alias; - myphar->alias_len = size; + actual_alias = zend_string_init(buf, size, myphar->is_persistent); + if (myphar->is_persistent) { + GC_MAKE_PERSISTENT_LOCAL(actual_alias); + } php_stream_seek(fp, pos, SEEK_SET); } else { if (error) { spprintf(error, 4096, "phar error: Unable to read alias from tar-based phar \"%s\"", fname); } - php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -588,6 +628,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -605,6 +648,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -619,6 +665,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l /* ensure signature set */ if (!myphar->is_data && PHAR_G(require_hash) && !myphar->signature) { php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); if (error) { spprintf(error, 0, "tar-based phar \"%s\" does not have a signature", fname); @@ -651,6 +700,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\" to phar registry", fname); } php_stream_close(fp); + if (actual_alias) { + zend_string_release_ex(actual_alias, myphar->is_persistent); + } phar_destroy_phar_data(myphar); return FAILURE; } @@ -662,22 +714,26 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l myphar->is_temporary_alias = 0; - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), actual_alias, myphar->alias_len))) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), actual_alias))) { if (SUCCESS != phar_free_alias(fd_ptr)) { if (error) { spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname); } zend_hash_str_del(&(PHAR_G(phar_fname_map)), myphar->fname, fname_len); + zend_string_release_ex(actual_alias, myphar->is_persistent); return FAILURE; } } - - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), actual_alias, myphar->alias_len, myphar); + + myphar->alias = actual_alias; + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), actual_alias, myphar); + zend_string_release_ex(actual_alias, myphar->is_persistent); + } else { phar_archive_data *fd_ptr; - if (alias_len) { - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { + if (alias && ZSTR_LEN(alias)) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias))) { if (SUCCESS != phar_free_alias(fd_ptr)) { if (error) { spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname); @@ -686,12 +742,13 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l return FAILURE; } } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, myphar); - myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent); - myphar->alias_len = alias_len; + myphar->alias = zend_string_init(ZSTR_VAL(alias), ZSTR_LEN(alias), myphar->is_persistent); + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), myphar->alias, myphar); } else { - myphar->alias = pestrndup(myphar->fname, fname_len, myphar->is_persistent); - myphar->alias_len = fname_len; + myphar->alias = zend_string_init(myphar->fname, fname_len, myphar->is_persistent); + } + if (myphar->is_persistent) { + GC_MAKE_PERSISTENT_LOCAL(myphar->alias); } myphar->is_temporary_alias = 1; @@ -992,19 +1049,19 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze } /* set alias */ - if (!phar->is_temporary_alias && phar->alias_len) { + if (!phar->is_temporary_alias && phar) { entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { *error = estrdup("phar error: unable to create temporary file"); return EOF; } - if (phar->alias_len != php_stream_write(entry.fp, phar->alias, phar->alias_len)) { + if (ZSTR_LEN(phar->alias) != php_stream_write(entry.fp, ZSTR_VAL(phar->alias), ZSTR_LEN(phar->alias))) { spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname); php_stream_close(entry.fp); return EOF; } - entry.uncompressed_filesize = phar->alias_len; + entry.uncompressed_filesize = ZSTR_LEN(phar->alias); entry.filename = ZSTR_INIT_LITERAL(".phar/alias.txt", false); zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); diff --git a/ext/phar/util.c b/ext/phar/util.c index 8af0c488f5ca..e5d1c4a37783 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -305,7 +305,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data } if (*ZSTR_VAL(filename) == '.') { - if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) { efree(arch); return NULL; } @@ -474,7 +474,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co *ret = NULL; *error = NULL; - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) { + if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, error)) { return FAILURE; } @@ -619,7 +619,7 @@ ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(char *fnam is_dir = (path_len && path[path_len - 1] == '/') ? 1 : 0; - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) { + if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, error)) { return NULL; } @@ -953,7 +953,7 @@ zend_result phar_free_alias(const phar_archive_data *phar) /* {{{ */ * Looks up a phar archive in the filename map, connecting it to the alias * (if any) or returns null */ -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) /* {{{ */ +zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, zend_string *alias, char **error) /* {{{ */ { phar_archive_data *fd, *fd_ptr; char *my_realpath; @@ -968,40 +968,39 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz if (PHAR_G(last_phar) && fname_len == PHAR_G(last_phar_name_len) && !memcmp(fname, PHAR_G(last_phar_name), fname_len)) { *archive = PHAR_G(last_phar); - if (alias && alias_len) { + if (alias) { - if (!PHAR_G(last_phar)->is_temporary_alias && (alias_len != PHAR_G(last_phar)->alias_len || memcmp(PHAR_G(last_phar)->alias, alias, alias_len))) { + if (!PHAR_G(last_phar)->is_temporary_alias && !zend_string_equals(PHAR_G(last_phar)->alias, alias)) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, PHAR_G(last_phar)->fname, fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", ZSTR_VAL(alias), PHAR_G(last_phar)->fname, fname); } *archive = NULL; return FAILURE; } - if (PHAR_G(last_phar)->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len))) { - zend_hash_str_del(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len); + if (PHAR_G(last_phar)->alias) { + zend_hash_del(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias); } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, *archive); + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), alias, *archive); PHAR_G(last_alias) = alias; - PHAR_G(last_alias_len) = alias_len; } return SUCCESS; } - if (alias && alias_len && PHAR_G(last_phar) && alias_len == PHAR_G(last_alias_len) && !memcmp(alias, PHAR_G(last_alias), alias_len)) { + if (alias && PHAR_G(last_phar) && PHAR_G(last_alias) && zend_string_equals(alias, PHAR_G(last_alias))) { fd = PHAR_G(last_phar); fd_ptr = fd; goto alias_success; } - if (alias && alias_len) { - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { + if (alias) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias))) { alias_success: if (fname && (fname_len != fd_ptr->fname_len || strncmp(fname, fd_ptr->fname, fname_len))) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", ZSTR_VAL(alias), fd_ptr->fname, fname); } if (SUCCESS == phar_free_alias(fd_ptr)) { if (error) { @@ -1018,12 +1017,11 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz PHAR_G(last_phar_name) = fd->fname; PHAR_G(last_phar_name_len) = fd->fname_len; PHAR_G(last_alias) = alias; - PHAR_G(last_alias_len) = alias_len; return SUCCESS; } - if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_alias, alias, alias_len))) { + if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_find_ptr(&cached_alias, alias))) { goto alias_success; } } @@ -1037,26 +1035,25 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz *archive = fd_ptr; fd = fd_ptr; - if (alias && alias_len) { - if (!fd->is_temporary_alias && (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len))) { + if (alias) { + if (!fd->is_temporary_alias && !zend_string_equals(alias, fd->alias)) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", ZSTR_VAL(alias), fd_ptr->fname, fname); } return FAILURE; } - if (fd->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), fd->alias, fd->alias_len))) { - zend_hash_str_del(&(PHAR_G(phar_alias_map)), fd->alias, fd->alias_len); + if (fd->alias) { + zend_hash_del(&(PHAR_G(phar_alias_map)), fd->alias); } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd); + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), alias, fd); } PHAR_G(last_phar) = fd; PHAR_G(last_phar_name) = fd->fname; PHAR_G(last_phar_name_len) = fd->fname_len; PHAR_G(last_alias) = fd->alias; - PHAR_G(last_alias_len) = fd->alias_len; return SUCCESS; } @@ -1067,10 +1064,10 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz /* this could be problematic - alias should never be different from manifest alias for cached phars */ - if (!fd->is_temporary_alias && alias && alias_len) { - if (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len)) { + if (!fd->is_temporary_alias && alias) { + if (!zend_string_equals(alias, fd->alias)) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", ZSTR_VAL(alias), fd_ptr->fname, fname); } return FAILURE; } @@ -1080,7 +1077,6 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz PHAR_G(last_phar_name) = fd->fname; PHAR_G(last_phar_name_len) = fd->fname_len; PHAR_G(last_alias) = fd->alias; - PHAR_G(last_alias_len) = fd->alias_len; return SUCCESS; } @@ -1092,7 +1088,6 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz PHAR_G(last_phar_name) = fd->fname; PHAR_G(last_phar_name_len) = fd->fname_len; PHAR_G(last_alias) = fd->alias; - PHAR_G(last_alias_len) = fd->alias_len; return SUCCESS; } @@ -1104,7 +1099,6 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz PHAR_G(last_phar_name) = fd->fname; PHAR_G(last_phar_name_len) = fd->fname_len; PHAR_G(last_alias) = fd->alias; - PHAR_G(last_alias_len) = fd->alias_len; return SUCCESS; } @@ -1128,8 +1122,8 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz *archive = fd_ptr; fd = fd_ptr; - if (alias && alias_len) { - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd); + if (alias) { + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), alias, fd); } efree(my_realpath); @@ -1138,7 +1132,6 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz PHAR_G(last_phar_name) = fd->fname; PHAR_G(last_phar_name_len) = fd->fname_len; PHAR_G(last_alias) = fd->alias; - PHAR_G(last_alias_len) = fd->alias_len; return SUCCESS; } @@ -2031,7 +2024,7 @@ static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */ phar->ext = phar->fname + (phar->ext - fname); if (phar->alias) { - phar->alias = estrndup(phar->alias, phar->alias_len); + phar->alias = zend_string_copy(phar->alias); } if (phar->signature) { @@ -2078,7 +2071,7 @@ zend_result phar_copy_on_write(phar_archive_data **pphar) /* {{{ */ PHAR_G(last_alias) = NULL; PHAR_G(last_phar_name) = NULL; - if (newpphar->alias_len && NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), newpphar->alias, newpphar->alias_len, newpphar)) { + if (newpphar->alias && NULL == zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), newpphar->alias, newpphar)) { zend_hash_str_del(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len); return FAILURE; } diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 5509b7582f43..bca347771a96 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -224,7 +224,7 @@ static char *phar_find_eocd(const char *s, size_t n) * This is used by phar_open_from_fp to process a zip-based phar, but can be called * directly. */ -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_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, zend_string *alias, phar_archive_data** pphar, char **error) /* {{{ */ { phar_zip_dir_end locator; char buf[sizeof(locator) + 65536]; @@ -341,10 +341,6 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l entry.fp_type = PHAR_FP; entry.is_persistent = mydata->is_persistent; #define PHAR_ZIP_FAIL(errmsg) \ - if (actual_alias) { \ - zend_string_release_ex(actual_alias, 0); \ - actual_alias = NULL; \ - } \ zend_hash_destroy(&mydata->manifest); \ HT_INVALIDATE(&mydata->manifest); \ zend_hash_destroy(&mydata->mounted_dirs); \ @@ -618,7 +614,6 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l zend_off_t restore_pos = php_stream_tell(fp); php_stream_seek(fp, entry.offset, SEEK_SET); - mydata->alias_len = entry.uncompressed_filesize; if (entry.flags & PHAR_ENT_COMPRESSED_GZ) { filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp)); @@ -630,7 +625,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - entry.uncompressed_filesize = ZSTR_LEN(actual_alias); + entry.uncompressed_filesize = actual_alias ? ZSTR_LEN(actual_alias) : 0; if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); @@ -650,7 +645,8 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - entry.uncompressed_filesize = ZSTR_LEN(actual_alias); + entry.uncompressed_filesize = actual_alias ? ZSTR_LEN(actual_alias) : 0; + printf("++++++++arrrr%s--", ZSTR_VAL(actual_alias)); if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); @@ -661,7 +657,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_remove(filter, 1); } else { actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); - entry.uncompressed_filesize = ZSTR_LEN(actual_alias); + entry.uncompressed_filesize = actual_alias ? ZSTR_LEN(actual_alias) : 0; if (!entry.uncompressed_filesize) { zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -691,7 +687,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l zend_hash_str_add_ptr(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len, mydata); - if (actual_alias != NULL) { + if (actual_alias) { phar_archive_data *fd_ptr; if (!phar_validate_alias(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias))) { @@ -705,7 +701,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l mydata->is_temporary_alias = 0; - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias)))) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), actual_alias))) { if (SUCCESS != phar_free_alias(fd_ptr)) { if (error) { spprintf(error, 4096, "phar error: Unable to add zip-based phar \"%s\" with implicit alias, alias is already in use", fname); @@ -716,18 +712,18 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l } } + mydata->alias = zend_string_init(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias), entry.is_persistent); if (entry.is_persistent) { - mydata->alias = pestrndup(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias), 1); - } else { - mydata->alias = estrndup(ZSTR_VAL(actual_alias), ZSTR_LEN(actual_alias)); + GC_MAKE_PERSISTENT_LOCAL(mydata->alias); } + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), actual_alias, mydata); zend_string_release_ex(actual_alias, 0); - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), mydata->alias, mydata->alias_len, mydata); + } else { phar_archive_data *fd_ptr; - if (alias_len) { - if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { + if (alias && ZSTR_LEN(alias)) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias))) { if (SUCCESS != phar_free_alias(fd_ptr)) { if (error) { spprintf(error, 4096, "phar error: Unable to add zip-based phar \"%s\" with explicit alias, alias is already in use", fname); @@ -736,13 +732,14 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l return FAILURE; } } - - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata); - mydata->alias = pestrndup(alias, alias_len, mydata->is_persistent); - mydata->alias_len = alias_len; + mydata->alias = zend_string_init(ZSTR_VAL(alias), ZSTR_LEN(alias), mydata->is_persistent); + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), mydata->alias, mydata); } else { - mydata->alias = pestrndup(mydata->fname, fname_len, mydata->is_persistent); - mydata->alias_len = fname_len; + mydata->alias = zend_string_init(mydata->fname, fname_len, mydata->is_persistent); + } + + if (mydata->is_persistent) { + GC_MAKE_PERSISTENT_LOCAL(myphar->alias); } mydata->is_temporary_alias = 1; @@ -759,10 +756,10 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l /** * Create or open a zip-based phar for writing */ -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(char *fname, size_t fname_len, zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; - zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); + zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, is_data, options, &phar, error); if (FAILURE == ret) { return FAILURE; @@ -1216,19 +1213,19 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *phar, ze } /* set alias */ - if (!phar->is_temporary_alias && phar->alias_len) { + if (!phar->is_temporary_alias && phar->alias) { entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { *error = estrdup("phar error: unable to create temporary file"); return EOF; } - if (phar->alias_len != php_stream_write(entry.fp, phar->alias, phar->alias_len)) { + if (ZSTR_LEN(phar->alias) != php_stream_write(entry.fp, ZSTR_VAL(phar->alias), ZSTR_LEN(phar->alias))) { php_stream_close(entry.fp); spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname); return EOF; } - entry.uncompressed_filesize = entry.compressed_filesize = phar->alias_len; + entry.uncompressed_filesize = entry.compressed_filesize = ZSTR_LEN(phar->alias); entry.filename = ZSTR_INIT_LITERAL(".phar/alias.txt", false); zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); @@ -1237,8 +1234,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *phar, ze } /* register alias */ - if (phar->alias_len) { - if (FAILURE == phar_get_archive(&phar, phar->fname, phar->fname_len, phar->alias, phar->alias_len, error)) { + if (phar->alias) { + if (FAILURE == phar_get_archive(&phar, phar->fname, phar->fname_len, phar->alias, error)) { return EOF; } } From 3a623c61cbaef99a1d728174c0b3aa347ffc1b71 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 18 Apr 2026 15:40:29 +0530 Subject: [PATCH 06/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/phar/util.c b/ext/phar/util.c index e5d1c4a37783..9ddc9313b4fe 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -2024,7 +2024,7 @@ static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */ phar->ext = phar->fname + (phar->ext - fname); if (phar->alias) { - phar->alias = zend_string_copy(phar->alias); + zend_string_addref(phar->alias); } if (phar->signature) { From 35abbaf6d9cdc05be73b5a42e595b21e9e677e16 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 17 Apr 2026 19:04:47 +0100 Subject: [PATCH 07/15] ext/phar/utils.c: Change if guard to assertion in phar_get_link_location() This condition is checked before calling it at the unique call site, effectively being dead code. An assertion is clearer. --- ext/phar/util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/phar/util.c b/ext/phar/util.c index 9ddc9313b4fe..0f5060499ee8 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -41,9 +41,9 @@ static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, ze static char *phar_get_link_location(phar_entry_info *entry) /* {{{ */ { char *p, *ret = NULL; - if (!entry->link) { - return NULL; - } + + ZEND_ASSERT(entry->link); + if (entry->link[0] == '/') { return estrdup(entry->link + 1); } From f5b17c292a0763b505be099dae056e096de53e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Fri, 17 Apr 2026 22:39:32 +0200 Subject: [PATCH 08/15] gen_stub: fix invalid C variable name for namespaced types in union/intersection type list (#21717) When generating a union or intersection type list with multiple class types, the variable holding each zend_string* was declared using toVarEscapedName() (backslashes replaced by underscores), but the subsequent ZEND_TYPE_INIT_CLASS() reference used toEscapedName() (backslashes escaped as \\), producing an invalid C identifier. --- build/gen_stub.php | 4 +-- ext/zend_test/test.c | 2 ++ ext/zend_test/test.stub.php | 4 +++ ext/zend_test/test_arginfo.h | 38 ++++++++++++++++++++++- ext/zend_test/test_decl.h | 8 ++--- ext/zend_test/test_legacy_arginfo.h | 24 +++++++++++++- ext/zend_test/tests/gen_stub_test_01.phpt | 8 +++++ 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index ce1a23866610..c189abd03471 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2375,8 +2375,8 @@ protected function getTypeCode(string $variableLikeName, string &$code): string $code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->num_types = $classTypeCount;\n"; foreach ($arginfoType->classTypes as $k => $classType) { - $escapedClassName = $classType->toEscapedName(); - $code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS({$variableLikeType}_{$variableLikeName}_class_{$escapedClassName}, 0, 0);\n"; + $varEscapedClassName = $classType->toVarEscapedName(); + $code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS({$variableLikeType}_{$variableLikeName}_class_{$varEscapedClassName}, 0, 0);\n"; } $typeMaskCode = $this->type->toArginfoType()->toTypeMask(); diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 02252a2d43ed..96f8db83c116 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -65,6 +65,7 @@ static zend_class_entry *zend_test_forbid_dynamic_call; static zend_class_entry *zend_test_ns_foo_class; static zend_class_entry *zend_test_ns_unlikely_compile_error_class; static zend_class_entry *zend_test_ns_not_unlikely_compile_error_class; +static zend_class_entry *zend_test_ns_bar_class; static zend_class_entry *zend_test_ns2_foo_class; static zend_class_entry *zend_test_ns2_ns_foo_class; static zend_class_entry *zend_test_unit_enum; @@ -1567,6 +1568,7 @@ PHP_MINIT_FUNCTION(zend_test) zend_test_ns_foo_class = register_class_ZendTestNS_Foo(); zend_test_ns_unlikely_compile_error_class = register_class_ZendTestNS_UnlikelyCompileError(); zend_test_ns_not_unlikely_compile_error_class = register_class_ZendTestNS_NotUnlikelyCompileError(); + zend_test_ns_bar_class = register_class_ZendTestNS_Bar(); zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo(); zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo(); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index e102082c6a95..f4844eb0681f 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -363,6 +363,8 @@ class Foo { public function method(): int {} } + interface Bar {} + class UnlikelyCompileError { /* This method signature would create a compile error due to the string * "ZendTestNS\UnlikelyCompileError" in the generated macro call */ @@ -383,6 +385,8 @@ public function method(): ?NotUnlikelyCompileError {} class Foo { public ZendSubNS\Foo $foo; + public ZendSubNS\Foo&\ZendTestNS\Bar $intersectionProp; + public ZendSubNS\Foo|\ZendTestNS\Bar $unionProp; public function method(): void {} } diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 30297234fc87..d2bdbd72db47 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit test.stub.php instead. - * Stub hash: 46178f5fa88681da91d831250f2f00c45e914624 + * Stub hash: 9a23b7d5305982930579428a345ded725ff5145f * Has decl header: yes */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_trigger_bailout, 0, 0, IS_NEVER, 0) @@ -1294,6 +1294,16 @@ static zend_class_entry *register_class_ZendTestNS_Foo(void) return class_entry; } +static zend_class_entry *register_class_ZendTestNS_Bar(void) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "ZendTestNS", "Bar", NULL); + class_entry = zend_register_internal_interface(&ce); + + return class_entry; +} + static zend_class_entry *register_class_ZendTestNS_UnlikelyCompileError(void) { zend_class_entry ce, *class_entry; @@ -1340,6 +1350,32 @@ static zend_class_entry *register_class_ZendTestNS2_Foo(void) zend_declare_typed_property(class_entry, property_foo_name, &property_foo_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_foo_class_ZendTestNS2_ZendSubNS_Foo, 0, 0)); zend_string_release_ex(property_foo_name, true); + zval property_intersectionProp_default_value; + ZVAL_UNDEF(&property_intersectionProp_default_value); + zend_string *property_intersectionProp_name = zend_string_init("intersectionProp", sizeof("intersectionProp") - 1, true); + zend_string *property_intersectionProp_class_ZendTestNS2_ZendSubNS_Foo = zend_string_init("ZendTestNS2\\ZendSubNS\\Foo", sizeof("ZendTestNS2\\ZendSubNS\\Foo") - 1, 1); + zend_string *property_intersectionProp_class_ZendTestNS_Bar = zend_string_init("ZendTestNS\\Bar", sizeof("ZendTestNS\\Bar") - 1, 1); + zend_type_list *property_intersectionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2)); + property_intersectionProp_type_list->num_types = 2; + property_intersectionProp_type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(property_intersectionProp_class_ZendTestNS2_ZendSubNS_Foo, 0, 0); + property_intersectionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_intersectionProp_class_ZendTestNS_Bar, 0, 0); + zend_type property_intersectionProp_type = ZEND_TYPE_INIT_INTERSECTION(property_intersectionProp_type_list, 0); + zend_declare_typed_property(class_entry, property_intersectionProp_name, &property_intersectionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_intersectionProp_type); + zend_string_release_ex(property_intersectionProp_name, true); + + zval property_unionProp_default_value; + ZVAL_UNDEF(&property_unionProp_default_value); + zend_string *property_unionProp_name = zend_string_init("unionProp", sizeof("unionProp") - 1, true); + zend_string *property_unionProp_class_ZendTestNS2_ZendSubNS_Foo = zend_string_init("ZendTestNS2\\ZendSubNS\\Foo", sizeof("ZendTestNS2\\ZendSubNS\\Foo") - 1, 1); + zend_string *property_unionProp_class_ZendTestNS_Bar = zend_string_init("ZendTestNS\\Bar", sizeof("ZendTestNS\\Bar") - 1, 1); + zend_type_list *property_unionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2)); + property_unionProp_type_list->num_types = 2; + property_unionProp_type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(property_unionProp_class_ZendTestNS2_ZendSubNS_Foo, 0, 0); + property_unionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_unionProp_class_ZendTestNS_Bar, 0, 0); + zend_type property_unionProp_type = ZEND_TYPE_INIT_UNION(property_unionProp_type_list, 0); + zend_declare_typed_property(class_entry, property_unionProp_name, &property_unionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_unionProp_type); + zend_string_release_ex(property_unionProp_name, true); + return class_entry; } diff --git a/ext/zend_test/test_decl.h b/ext/zend_test/test_decl.h index ed0874f51e72..816e03919a13 100644 --- a/ext/zend_test/test_decl.h +++ b/ext/zend_test/test_decl.h @@ -1,8 +1,8 @@ /* This is a generated file, edit test.stub.php instead. - * Stub hash: 46178f5fa88681da91d831250f2f00c45e914624 */ + * Stub hash: 9a23b7d5305982930579428a345ded725ff5145f */ -#ifndef ZEND_TEST_DECL_46178f5fa88681da91d831250f2f00c45e914624_H -#define ZEND_TEST_DECL_46178f5fa88681da91d831250f2f00c45e914624_H +#ifndef ZEND_TEST_DECL_9a23b7d5305982930579428a345ded725ff5145f_H +#define ZEND_TEST_DECL_9a23b7d5305982930579428a345ded725ff5145f_H typedef enum zend_enum_ZendTestUnitEnum { ZEND_ENUM_ZendTestUnitEnum_Foo = 1, @@ -27,4 +27,4 @@ typedef enum zend_enum_ZendTestEnumWithInterface { ZEND_ENUM_ZendTestEnumWithInterface_Bar = 2, } zend_enum_ZendTestEnumWithInterface; -#endif /* ZEND_TEST_DECL_46178f5fa88681da91d831250f2f00c45e914624_H */ +#endif /* ZEND_TEST_DECL_9a23b7d5305982930579428a345ded725ff5145f_H */ diff --git a/ext/zend_test/test_legacy_arginfo.h b/ext/zend_test/test_legacy_arginfo.h index 3dcdad8ff6c7..b4a07503ad0f 100644 --- a/ext/zend_test/test_legacy_arginfo.h +++ b/ext/zend_test/test_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit test.stub.php instead. - * Stub hash: 46178f5fa88681da91d831250f2f00c45e914624 + * Stub hash: 9a23b7d5305982930579428a345ded725ff5145f * Has decl header: yes */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_trigger_bailout, 0, 0, 0) @@ -1029,6 +1029,16 @@ static zend_class_entry *register_class_ZendTestNS_Foo(void) return class_entry; } +static zend_class_entry *register_class_ZendTestNS_Bar(void) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "ZendTestNS", "Bar", NULL); + class_entry = zend_register_internal_interface(&ce); + + return class_entry; +} + static zend_class_entry *register_class_ZendTestNS_UnlikelyCompileError(void) { zend_class_entry ce, *class_entry; @@ -1074,6 +1084,18 @@ static zend_class_entry *register_class_ZendTestNS2_Foo(void) zend_declare_property_ex(class_entry, property_foo_name, &property_foo_default_value, ZEND_ACC_PUBLIC, NULL); zend_string_release_ex(property_foo_name, true); + zval property_intersectionProp_default_value; + ZVAL_NULL(&property_intersectionProp_default_value); + zend_string *property_intersectionProp_name = zend_string_init("intersectionProp", sizeof("intersectionProp") - 1, true); + zend_declare_property_ex(class_entry, property_intersectionProp_name, &property_intersectionProp_default_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release_ex(property_intersectionProp_name, true); + + zval property_unionProp_default_value; + ZVAL_NULL(&property_unionProp_default_value); + zend_string *property_unionProp_name = zend_string_init("unionProp", sizeof("unionProp") - 1, true); + zend_declare_property_ex(class_entry, property_unionProp_name, &property_unionProp_default_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release_ex(property_unionProp_name, true); + return class_entry; } diff --git a/ext/zend_test/tests/gen_stub_test_01.phpt b/ext/zend_test/tests/gen_stub_test_01.phpt index 0f5d525322d6..3126eb61631f 100644 --- a/ext/zend_test/tests/gen_stub_test_01.phpt +++ b/ext/zend_test/tests/gen_stub_test_01.phpt @@ -18,11 +18,19 @@ var_dump($foo); object(ZendTestNS2\Foo)#%d (%d) { ["foo"]=> uninitialized(ZendTestNS2\ZendSubNS\Foo) + ["intersectionProp"]=> + uninitialized(ZendTestNS2\ZendSubNS\Foo&ZendTestNS\Bar) + ["unionProp"]=> + uninitialized(ZendTestNS2\ZendSubNS\Foo|ZendTestNS\Bar) } object(ZendTestNS2\Foo)#%d (%d) { ["foo"]=> object(ZendTestNS2\ZendSubNS\Foo)#%d (%d) { } + ["intersectionProp"]=> + uninitialized(ZendTestNS2\ZendSubNS\Foo&ZendTestNS\Bar) + ["unionProp"]=> + uninitialized(ZendTestNS2\ZendSubNS\Foo|ZendTestNS\Bar) } object(ZendTestNS\UnlikelyCompileError)#%d (%d) { } From 9e6857c804f9e8b4ad781762c0a660c6a16a9de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Fri, 17 Apr 2026 23:45:34 +0200 Subject: [PATCH 09/15] gen_stub: support use statements in stub files (#21784) Stmt\Use_ and Stmt\GroupUse nodes were not handled in handleStatements(), causing an "Unexpected node" exception when use statements appeared in stub files. Since NameResolver resolves all names to their fully qualified form before handleStatements() runs, these nodes can simply be skipped. --- build/gen_stub.php | 5 +++++ ext/zend_test/test.stub.php | 7 +++++++ ext/zend_test/test_arginfo.h | 23 ++++++++++++++++++++++- ext/zend_test/test_decl.h | 8 ++++---- ext/zend_test/test_legacy_arginfo.h | 20 +++++++++++++++++++- ext/zend_test/tests/gen_stub_test_01.phpt | 12 ++++++++++++ 6 files changed, 69 insertions(+), 6 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index c189abd03471..eca1ab3e8c13 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4261,6 +4261,11 @@ private function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPri continue; } + if ($stmt instanceof Stmt\Use_ || $stmt instanceof Stmt\GroupUse) { + // use statements are resolved by NameResolver before this point + continue; + } + if ($stmt instanceof Stmt\Const_) { foreach ($stmt->consts as $const) { $this->constInfos[] = parseConstLike( diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index f4844eb0681f..c9d367d5553f 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -380,6 +380,10 @@ public function method(): ?NotUnlikelyCompileError {} namespace ZendTestNS2 { + use ZendTestNS\Foo as FooAlias; + use ZendTestNS\UnlikelyCompileError; + use ZendTestNS\{NotUnlikelyCompileError}; + /** @var string */ const ZEND_CONSTANT_A = "namespaced"; @@ -387,6 +391,9 @@ class Foo { public ZendSubNS\Foo $foo; public ZendSubNS\Foo&\ZendTestNS\Bar $intersectionProp; public ZendSubNS\Foo|\ZendTestNS\Bar $unionProp; + public FooAlias $fooAlias; + public UnlikelyCompileError $unlProp; + public NotUnlikelyCompileError $notUnlProp; public function method(): void {} } diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index d2bdbd72db47..a4da05df2ffb 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit test.stub.php instead. - * Stub hash: 9a23b7d5305982930579428a345ded725ff5145f + * Stub hash: dcb089a336c6c3e6c685762057dcedcb393508a7 * Has decl header: yes */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_trigger_bailout, 0, 0, IS_NEVER, 0) @@ -1376,6 +1376,27 @@ static zend_class_entry *register_class_ZendTestNS2_Foo(void) zend_declare_typed_property(class_entry, property_unionProp_name, &property_unionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_unionProp_type); zend_string_release_ex(property_unionProp_name, true); + zval property_fooAlias_default_value; + ZVAL_UNDEF(&property_fooAlias_default_value); + zend_string *property_fooAlias_name = zend_string_init("fooAlias", sizeof("fooAlias") - 1, true); + zend_string *property_fooAlias_class_ZendTestNS_Foo = zend_string_init("ZendTestNS\\Foo", sizeof("ZendTestNS\\Foo")-1, 1); + zend_declare_typed_property(class_entry, property_fooAlias_name, &property_fooAlias_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_fooAlias_class_ZendTestNS_Foo, 0, 0)); + zend_string_release_ex(property_fooAlias_name, true); + + zval property_unlProp_default_value; + ZVAL_UNDEF(&property_unlProp_default_value); + zend_string *property_unlProp_name = zend_string_init("unlProp", sizeof("unlProp") - 1, true); + zend_string *property_unlProp_class_ZendTestNS_UnlikelyCompileError = zend_string_init("ZendTestNS\\\125nlikelyCompileError", sizeof("ZendTestNS\\\125nlikelyCompileError")-1, 1); + zend_declare_typed_property(class_entry, property_unlProp_name, &property_unlProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_unlProp_class_ZendTestNS_UnlikelyCompileError, 0, 0)); + zend_string_release_ex(property_unlProp_name, true); + + zval property_notUnlProp_default_value; + ZVAL_UNDEF(&property_notUnlProp_default_value); + zend_string *property_notUnlProp_name = zend_string_init("notUnlProp", sizeof("notUnlProp") - 1, true); + zend_string *property_notUnlProp_class_ZendTestNS_NotUnlikelyCompileError = zend_string_init("ZendTestNS\\\116otUnlikelyCompileError", sizeof("ZendTestNS\\\116otUnlikelyCompileError")-1, 1); + zend_declare_typed_property(class_entry, property_notUnlProp_name, &property_notUnlProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_notUnlProp_class_ZendTestNS_NotUnlikelyCompileError, 0, 0)); + zend_string_release_ex(property_notUnlProp_name, true); + return class_entry; } diff --git a/ext/zend_test/test_decl.h b/ext/zend_test/test_decl.h index 816e03919a13..bc2ebaa93c3b 100644 --- a/ext/zend_test/test_decl.h +++ b/ext/zend_test/test_decl.h @@ -1,8 +1,8 @@ /* This is a generated file, edit test.stub.php instead. - * Stub hash: 9a23b7d5305982930579428a345ded725ff5145f */ + * Stub hash: dcb089a336c6c3e6c685762057dcedcb393508a7 */ -#ifndef ZEND_TEST_DECL_9a23b7d5305982930579428a345ded725ff5145f_H -#define ZEND_TEST_DECL_9a23b7d5305982930579428a345ded725ff5145f_H +#ifndef ZEND_TEST_DECL_dcb089a336c6c3e6c685762057dcedcb393508a7_H +#define ZEND_TEST_DECL_dcb089a336c6c3e6c685762057dcedcb393508a7_H typedef enum zend_enum_ZendTestUnitEnum { ZEND_ENUM_ZendTestUnitEnum_Foo = 1, @@ -27,4 +27,4 @@ typedef enum zend_enum_ZendTestEnumWithInterface { ZEND_ENUM_ZendTestEnumWithInterface_Bar = 2, } zend_enum_ZendTestEnumWithInterface; -#endif /* ZEND_TEST_DECL_9a23b7d5305982930579428a345ded725ff5145f_H */ +#endif /* ZEND_TEST_DECL_dcb089a336c6c3e6c685762057dcedcb393508a7_H */ diff --git a/ext/zend_test/test_legacy_arginfo.h b/ext/zend_test/test_legacy_arginfo.h index b4a07503ad0f..b446a0f9a293 100644 --- a/ext/zend_test/test_legacy_arginfo.h +++ b/ext/zend_test/test_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit test.stub.php instead. - * Stub hash: 9a23b7d5305982930579428a345ded725ff5145f + * Stub hash: dcb089a336c6c3e6c685762057dcedcb393508a7 * Has decl header: yes */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_trigger_bailout, 0, 0, 0) @@ -1096,6 +1096,24 @@ static zend_class_entry *register_class_ZendTestNS2_Foo(void) zend_declare_property_ex(class_entry, property_unionProp_name, &property_unionProp_default_value, ZEND_ACC_PUBLIC, NULL); zend_string_release_ex(property_unionProp_name, true); + zval property_fooAlias_default_value; + ZVAL_NULL(&property_fooAlias_default_value); + zend_string *property_fooAlias_name = zend_string_init("fooAlias", sizeof("fooAlias") - 1, true); + zend_declare_property_ex(class_entry, property_fooAlias_name, &property_fooAlias_default_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release_ex(property_fooAlias_name, true); + + zval property_unlProp_default_value; + ZVAL_NULL(&property_unlProp_default_value); + zend_string *property_unlProp_name = zend_string_init("unlProp", sizeof("unlProp") - 1, true); + zend_declare_property_ex(class_entry, property_unlProp_name, &property_unlProp_default_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release_ex(property_unlProp_name, true); + + zval property_notUnlProp_default_value; + ZVAL_NULL(&property_notUnlProp_default_value); + zend_string *property_notUnlProp_name = zend_string_init("notUnlProp", sizeof("notUnlProp") - 1, true); + zend_declare_property_ex(class_entry, property_notUnlProp_name, &property_notUnlProp_default_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release_ex(property_notUnlProp_name, true); + return class_entry; } diff --git a/ext/zend_test/tests/gen_stub_test_01.phpt b/ext/zend_test/tests/gen_stub_test_01.phpt index 3126eb61631f..0cda0651bee3 100644 --- a/ext/zend_test/tests/gen_stub_test_01.phpt +++ b/ext/zend_test/tests/gen_stub_test_01.phpt @@ -22,6 +22,12 @@ object(ZendTestNS2\Foo)#%d (%d) { uninitialized(ZendTestNS2\ZendSubNS\Foo&ZendTestNS\Bar) ["unionProp"]=> uninitialized(ZendTestNS2\ZendSubNS\Foo|ZendTestNS\Bar) + ["fooAlias"]=> + uninitialized(ZendTestNS\Foo) + ["unlProp"]=> + uninitialized(ZendTestNS\UnlikelyCompileError) + ["notUnlProp"]=> + uninitialized(ZendTestNS\NotUnlikelyCompileError) } object(ZendTestNS2\Foo)#%d (%d) { ["foo"]=> @@ -31,6 +37,12 @@ object(ZendTestNS2\Foo)#%d (%d) { uninitialized(ZendTestNS2\ZendSubNS\Foo&ZendTestNS\Bar) ["unionProp"]=> uninitialized(ZendTestNS2\ZendSubNS\Foo|ZendTestNS\Bar) + ["fooAlias"]=> + uninitialized(ZendTestNS\Foo) + ["unlProp"]=> + uninitialized(ZendTestNS\UnlikelyCompileError) + ["notUnlProp"]=> + uninitialized(ZendTestNS\NotUnlikelyCompileError) } object(ZendTestNS\UnlikelyCompileError)#%d (%d) { } From ead31bd02f70931a65ead85212e460534b07087f Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 18 Apr 2026 16:12:38 +0530 Subject: [PATCH 10/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/dirstream.c | 4 ++-- ext/phar/func_interceptors.c | 8 ++++---- ext/phar/phar_object.c | 4 ++-- ext/phar/util.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 5951fe0d8775..4b35c95b6ff0 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -355,7 +355,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL)) { phar = NULL; } @@ -481,7 +481,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL)) { phar = NULL; } diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index 20ce0e8d7258..5adffc850eb5 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -99,7 +99,7 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file defaults to within the current directory, so use this if possible */ phar_archive_data *phar; - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL)) { zend_string_release_ex(arch, false); return NULL; } @@ -494,7 +494,7 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0); if (arch) { /* fopen within phar, if :// is not in the url, then prepend phar:/// */ - zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL); zend_string_release_ex(arch, false); if (FAILURE == has_archive) { goto skip_phar; @@ -733,7 +733,7 @@ PHP_FUNCTION(phar_is_file) /* {{{ */ /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file within the current directory, so use this if possible */ - zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL); zend_string_release_ex(arch, false); if (has_archive == SUCCESS) { phar_entry_info *etemp; @@ -790,7 +790,7 @@ PHP_FUNCTION(phar_is_link) /* {{{ */ /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file within the current directory, so use this if possible */ - zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL); zend_string_release_ex(arch, false); if (has_archive == SUCCESS) { phar_entry_info *etemp; diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index f2d69d1fbe58..70d2e93ebb61 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1071,7 +1071,7 @@ static const spl_other_handler phar_spl_foreign_handler = { */ PHP_METHOD(Phar, __construct) { - char *fname, *alias = NULL, *error, *save_fname; + char *fname, *error, *save_fname; size_t fname_len, alias_len = 0; bool is_data; zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS; @@ -4414,7 +4414,7 @@ PHP_METHOD(PharFileInfo, __construct) RETURN_THROWS(); } - if (phar_open_from_filename(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, REPORT_ERRORS, &phar_data, &error) == FAILURE) { + if (phar_open_from_filename(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, REPORT_ERRORS, &phar_data, &error) == FAILURE) { zend_string_release_ex(arch, false); efree(entry); if (error) { diff --git a/ext/phar/util.c b/ext/phar/util.c index 41a5756b5e8b..a4bb5110c2ed 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -308,7 +308,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data } if (*ZSTR_VAL(filename) == '.') { - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, NULL)) { zend_string_release_ex(arch, false); return NULL; } From 9aef6eb18d88635de156e02cc6907154e6f4d83d Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 18 Apr 2026 18:34:36 +0530 Subject: [PATCH 11/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/phar_object.c | 2 +- ext/phar/tar.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 70d2e93ebb61..4899853e94a9 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1072,7 +1072,7 @@ static const spl_other_handler phar_spl_foreign_handler = { PHP_METHOD(Phar, __construct) { char *fname, *error, *save_fname; - size_t fname_len, alias_len = 0; + size_t fname_len; bool is_data; zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS; zend_long format = 0; diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 5c1f9ac9b966..60fab02bc778 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -1049,7 +1049,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze } /* set alias */ - if (!phar->is_temporary_alias && phar) { + if (phar && !phar->is_temporary_alias) { entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { *error = estrdup("phar error: unable to create temporary file"); From ae62c7c3a17c9d9b215d048ae30301f1f2d7503f Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 18 Apr 2026 19:33:01 +0530 Subject: [PATCH 12/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/tar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 60fab02bc778..c6cb9156a5c5 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -1049,7 +1049,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze } /* set alias */ - if (phar && !phar->is_temporary_alias) { + if (!phar->is_temporary_alias && phar->alias) { entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { *error = estrdup("phar error: unable to create temporary file"); From 2c2b3c92fb35a132b36b3f815723788f8a127479 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 18 Apr 2026 19:56:21 +0530 Subject: [PATCH 13/15] ext/phar: avoid redundant allocation by using zend_string for alias --- ext/phar/zip.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index bca347771a96..ff33874d2b2c 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -646,7 +646,6 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l php_stream_filter_append(&fp->readfilters, filter); actual_alias = php_stream_copy_to_mem(fp, entry.uncompressed_filesize, 0); entry.uncompressed_filesize = actual_alias ? ZSTR_LEN(actual_alias) : 0; - printf("++++++++arrrr%s--", ZSTR_VAL(actual_alias)); if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); From 98b7702ffd8b5ecab421d046ac359dc57cbea1d0 Mon Sep 17 00:00:00 2001 From: Arshid Date: Sat, 18 Apr 2026 21:20:19 +0530 Subject: [PATCH 14/15] Update ext/phar/phar_object.c Co-authored-by: Gina Peter Banyard --- ext/phar/phar_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 4899853e94a9..db909cf53913 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -2746,7 +2746,7 @@ PHP_METHOD(Phar, setAlias) zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), new_alias, phar_obj->archive); if (oldalias) { - zend_string_release_ex(oldalias, 0); + zend_string_release_ex(oldalias, false); } RETURN_TRUE; From c0fe93cb96082b603dd482d47cd06cdbea9d8cde Mon Sep 17 00:00:00 2001 From: Arshid Date: Sat, 18 Apr 2026 21:20:48 +0530 Subject: [PATCH 15/15] Update ext/phar/phar_object.c Co-authored-by: Gina Peter Banyard --- ext/phar/phar_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index db909cf53913..7fe23534a991 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -2732,7 +2732,7 @@ PHP_METHOD(Phar, setAlias) phar_flush(phar_obj->archive, &error); if (error) { - zend_string_release_ex(phar_obj->archive->alias, 0); + zend_string_release_ex(phar_obj->archive->alias, false); phar_obj->archive->alias = oldalias; phar_obj->archive->is_temporary_alias = old_temp; zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);