From cc837614163084ce522b7c5a3cf241c388f38311 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Oct 2025 22:13:12 +0200 Subject: [PATCH 1/8] phar: Fix file descriptor leak in phar_zip_flush() on failure. Closes GH-20228. --- NEWS | 1 + ext/phar/zip.c | 1 + 2 files changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 020927bb5ff6e..4345f86f98ec9 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,7 @@ PHP NEWS . Fix potential buffer length truncation due to usage of type int instead of type size_t. (Girgias) . Fix memory leak when openssl polyfill returns garbage. (nielsdos) + . Fix file descriptor leak in phar_zip_flush() on failure. (nielsdos) - Random: . Fix Randomizer::__serialize() w.r.t. INDIRECTs. (nielsdos) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index f1d0edd5bdff8..63c56108ed985 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -1246,6 +1246,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, zend_long len, int return EOF; } if (phar->alias_len != php_stream_write(entry.fp, phar->alias, phar->alias_len)) { + php_stream_close(entry.fp); if (error) { spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname); } From ce0df1a9d82dbb3166a889327ebb1c59a640f95f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Oct 2025 00:11:34 +0200 Subject: [PATCH 2/8] phar: Fix memory leak when opening temp file fails while trying to open gzip-compressed archive `filterparams` can leak if `php_stream_fopen_tmpfile()` fails. To solve this, move the temp file creation first. Closes GH-20220. --- NEWS | 2 ++ ext/phar/phar.c | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 4345f86f98ec9..27214db0b90e5 100644 --- a/NEWS +++ b/NEWS @@ -57,6 +57,8 @@ PHP NEWS of type size_t. (Girgias) . Fix memory leak when openssl polyfill returns garbage. (nielsdos) . Fix file descriptor leak in phar_zip_flush() on failure. (nielsdos) + . Fix memory leak when opening temp file fails while trying to open + gzip-compressed archive. (nielsdos) - Random: . Fix Randomizer::__serialize() w.r.t. INDIRECTs. (nielsdos) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index b7baf9e69ce4f..a9aff9489df01 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1672,6 +1672,12 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char if (!PHAR_G(has_zlib)) { MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file, enable zlib extension in php.ini") } + + /* entire file is gzip-compressed, uncompress to temporary file */ + if (!(temp = php_stream_fopen_tmpfile())) { + MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"") + } + array_init(&filterparams); /* this is defined in zlib's zconf.h */ #ifndef MAX_WBITS @@ -1679,11 +1685,6 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char #endif add_assoc_long_ex(&filterparams, "window", sizeof("window") - 1, MAX_WBITS + 32); - /* entire file is gzip-compressed, uncompress to temporary file */ - if (!(temp = php_stream_fopen_tmpfile())) { - MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"") - } - php_stream_rewind(fp); filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp)); From 920847efc6da1c6ecba490cb032e3d8a2d08f81f Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 21 Oct 2025 13:36:15 -0700 Subject: [PATCH 3/8] [ci skip] Update NEWS for PHP 8.5.0 RC4 --- NEWS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a79ac7b49c2bf..47db84c8f608f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.0RC3 +?? ??? ????, PHP 8.5.0RC4 + + +23 Oct 2025, PHP 8.5.0RC3 - Core: . Fixed bug GH-20113 (Missing new Foo(...) error in constant expressions). From d0ad286ec8615cdeda04a9e07c958e2f316d004d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Oct 2025 16:02:06 +0100 Subject: [PATCH 4/8] Zend: use type uint32_t for zend_lineno global --- Zend/zend_compile.c | 4 ++-- Zend/zend_compile.h | 2 +- Zend/zend_globals.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 27a07fffc733b..97e36d6b2498a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -519,7 +519,7 @@ ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */ } /* }}} */ -ZEND_API int zend_get_compiled_lineno(void) /* {{{ */ +ZEND_API uint32_t zend_get_compiled_lineno(void) /* {{{ */ { return CG(zend_lineno); } @@ -4697,7 +4697,7 @@ static const zend_frameless_function_info *find_frameless_function_info(zend_ast static uint32_t zend_compile_frameless_icall_ex(znode *result, zend_ast_list *args, zend_function *fbc, const zend_frameless_function_info *frameless_function_info, uint32_t type) { - int lineno = CG(zend_lineno); + uint32_t lineno = CG(zend_lineno); uint32_t num_args = frameless_function_info->num_args; uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler); znode arg_zvs[3]; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8321e4a03c1e3..e8b429bc4696a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -894,7 +894,7 @@ void shutdown_scanner(void); ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename); ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename); ZEND_API zend_string *zend_get_compiled_filename(void); -ZEND_API int zend_get_compiled_lineno(void); +ZEND_API uint32_t zend_get_compiled_lineno(void); ZEND_API size_t zend_get_scanned_file_offset(void); ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index fa24128ae20ed..df84a3d0f6b62 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -88,7 +88,7 @@ struct _zend_compiler_globals { zend_string *compiled_filename; - int zend_lineno; + uint32_t zend_lineno; zend_op_array *active_op_array; From f5e782ec2d0a4a6d01d95034bcde6f171d2f61c7 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Oct 2025 16:06:59 +0100 Subject: [PATCH 5/8] Zend: use type uint32_t for ticks_count global --- Zend/zend_globals.h | 2 +- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index df84a3d0f6b62..d43c60b95810b 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -204,7 +204,7 @@ struct _zend_executor_globals { zend_execute_data *current_observed_frame; - int ticks_count; + uint32_t ticks_count; zend_long precision; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 3c3065e156871..34e58639c64cd 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8006,7 +8006,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM) { USE_OPLINE - if ((uint32_t)++EG(ticks_count) >= opline->extended_value) { + if (++EG(ticks_count) >= opline->extended_value) { EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 50870ce463de3..cc8bc51a7f4ea 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3278,7 +3278,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_TICKS_SPEC_HA { USE_OPLINE - if ((uint32_t)++EG(ticks_count) >= opline->extended_value) { + if (++EG(ticks_count) >= opline->extended_value) { EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); @@ -58798,7 +58798,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_TICKS_SPEC_TAILCAL { USE_OPLINE - if ((uint32_t)++EG(ticks_count) >= opline->extended_value) { + if (++EG(ticks_count) >= opline->extended_value) { EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); From 3db0ea682a8243f2aed6e89449a906c2adb33e88 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Oct 2025 16:13:46 +0100 Subject: [PATCH 6/8] Zend: use type uint32_t for lineno ini scanner global --- Zend/zend_globals.h | 2 +- Zend/zend_ini_parser.y | 2 +- Zend/zend_ini_scanner.h | 2 +- Zend/zend_ini_scanner.l | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index d43c60b95810b..ef81ae5faaf25 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -343,7 +343,7 @@ struct _zend_ini_scanner_globals { zend_stack state_stack; zend_string *filename; - int lineno; + uint32_t lineno; /* Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW, ZEND_INI_SCANNER_TYPED */ int scanner_mode; diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 5f788f152fb6a..748ccd2235a6d 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -205,7 +205,7 @@ static ZEND_COLD void ini_error(const char *msg) error_buf_len = 128 + (int)strlen(msg) + (int)strlen(currently_parsed_filename); /* should be more than enough */ error_buf = (char *) emalloc(error_buf_len); - sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno()); + sprintf(error_buf, "%s in %s on line %" PRIu32 "\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno()); } else { error_buf = estrdup("Invalid configuration directive\n"); } diff --git a/Zend/zend_ini_scanner.h b/Zend/zend_ini_scanner.h index 62546413c7cb2..9a6c84fce4292 100644 --- a/Zend/zend_ini_scanner.h +++ b/Zend/zend_ini_scanner.h @@ -30,7 +30,7 @@ typedef struct _zend_file_handle zend_file_handle; #define ZEND_INI_SCANNER_TYPED 2 /* Typed mode. */ BEGIN_EXTERN_C() -ZEND_COLD int zend_ini_scanner_get_lineno(void); +ZEND_COLD uint32_t zend_ini_scanner_get_lineno(void); ZEND_COLD const char *zend_ini_scanner_get_filename(void); zend_result zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode); zend_result zend_ini_prepare_string_for_scanning(const char *str, int scanner_mode); diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index b87f4e33cc8f8..d3f71ba8bc340 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -230,7 +230,7 @@ void shutdown_ini_scanner(void) /* }}} */ /* {{{ zend_ini_scanner_get_lineno() */ -ZEND_COLD int zend_ini_scanner_get_lineno(void) +ZEND_COLD uint32_t zend_ini_scanner_get_lineno(void) { return SCNG(lineno); } From 51a4e06b08bd0242e50468efe178b323834e99eb Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Oct 2025 16:39:09 +0100 Subject: [PATCH 7/8] Zend: use type uint32_t for refcount CE field --- Zend/zend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend.h b/Zend/zend.h index 163b48015d9b8..2155be43c12b5 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -152,7 +152,7 @@ struct _zend_class_entry { zend_class_entry *parent; zend_string *parent_name; }; - int refcount; + uint32_t refcount; uint32_t ce_flags; uint32_t ce_flags2; From 40a42cffd81b7f01fed25b3f7d02cb4d2ead700d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Oct 2025 16:37:17 +0100 Subject: [PATCH 8/8] Zend: use type uint32_t for default_static_members_count CE field --- Zend/zend.h | 2 +- Zend/zend_object_handlers.c | 3 +-- ext/opcache/zend_persist.c | 3 +-- ext/opcache/zend_persist_calc.c | 4 +--- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 2155be43c12b5..aff48ca0e2068 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -157,7 +157,7 @@ struct _zend_class_entry { uint32_t ce_flags2; int default_properties_count; - int default_static_members_count; + uint32_t default_static_members_count; zval *default_properties_table; zval *default_static_members_table; ZEND_MAP_PTR_DEF(zval *, static_members_table); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 17676e8edea48..7514a1ddef82f 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -2006,7 +2006,6 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st ZEND_API void zend_class_init_statics(zend_class_entry *class_type) /* {{{ */ { - int i; zval *p; if (class_type->default_static_members_count && !CE_STATIC_MEMBERS(class_type)) { @@ -2015,7 +2014,7 @@ ZEND_API void zend_class_init_statics(zend_class_entry *class_type) /* {{{ */ } ZEND_MAP_PTR_SET(class_type->static_members_table, emalloc(sizeof(zval) * class_type->default_static_members_count)); - for (i = 0; i < class_type->default_static_members_count; i++) { + for (uint32_t i = 0; i < class_type->default_static_members_count; i++) { p = &class_type->default_static_members_table[i]; if (Z_TYPE_P(p) == IS_INDIRECT) { zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i]; diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index e1187b045b13e..ef69cceb0250b 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -967,12 +967,11 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) } } if (ce->default_static_members_table) { - int i; ce->default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count); /* Persist only static properties in this class. * Static properties from parent classes will be handled in class_copy_ctor and are marked with IS_INDIRECT */ - for (i = 0; i < ce->default_static_members_count; i++) { + for (uint32_t i = 0; i < ce->default_static_members_count; i++) { if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) { zend_persist_zval(&ce->default_static_members_table[i]); } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 3c763d239e5ff..c638d66619d0f 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -479,10 +479,8 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) } } if (ce->default_static_members_table) { - int i; - ADD_SIZE(sizeof(zval) * ce->default_static_members_count); - for (i = 0; i < ce->default_static_members_count; i++) { + for (uint32_t i = 0; i < ce->default_static_members_count; i++) { if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) { zend_persist_zval_calc(&ce->default_static_members_table[i]); }