From 6e664a04cb8fec50dd19195d4c9b29fb8ac83b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 10 Mar 2026 20:06:34 +0100 Subject: [PATCH 1/6] reflection: Check against the known string in `is_closure_invoke()` (#21402) This can likely succeed by just comparing pointers in a majority of cases. --- ext/reflection/php_reflection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 2f44d6be7bd2d..e44a746ff0846 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -191,7 +191,7 @@ static zend_always_inline uint32_t prop_get_flags(const property_reference *ref) static inline bool is_closure_invoke(const zend_class_entry *ce, const zend_string *lcname) { return ce == zend_ce_closure - && zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME); + && zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); } static zend_function *_copy_function(zend_function *fptr) /* {{{ */ From 3073948885d95c42ab4ce97109edb2b8f4dc6ed4 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 10 Mar 2026 20:27:48 +0100 Subject: [PATCH 2/6] Revert "ext/session: Fix memory leak due to multiple exception happening during session abort" This reverts commit 0acde1194513ff69c491f3c1ebe103c3774dc7fd. The patch is incorrect as described in GH-21200 in the post-merge comments. --- NEWS | 4 --- ext/session/session.c | 11 +----- ...sessionhandler_validateid_return_type.phpt | 35 ------------------- .../session_set_save_handler_class_012.phpt | 2 -- 4 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 ext/session/tests/sessionhandler_validateid_return_type.phpt diff --git a/NEWS b/NEWS index 9f2b1ed85e205..5380688ce3da2 100644 --- a/NEWS +++ b/NEWS @@ -13,10 +13,6 @@ PHP NEWS . Fixed preprocessor silently guarding PGSQL_SUPPRESS_TIMESTAMPS support due to a typo. (KentarouTakeda) -- Session: - . Fix memory leak due to multiple exception happening during session abort. - (arshidkv12) - - SNMP: . Fixed bug GH-21336 (SNMP::setSecurity() undefined behavior with NULL arguments). (David Carlier) diff --git a/ext/session/session.c b/ext/session/session.c index f8d963b489471..70e1673d87f54 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -41,7 +41,6 @@ #include "ext/standard/url_scanner_ex.h" #include "ext/standard/info.h" #include "zend_smart_str.h" -#include "zend_exceptions.h" #include "ext/standard/url.h" #include "ext/standard/basic_functions.h" #include "ext/standard/head.h" @@ -1744,16 +1743,8 @@ PHPAPI php_session_status php_get_session_status(void) static zend_result php_session_abort(void) /* {{{ */ { if (PS(session_status) == php_session_active) { - if ((PS(mod_data) || PS(mod_user_implemented)) && PS(mod)->s_close) { - zend_object *old_exception = EG(exception); - EG(exception) = NULL; - + if (PS(mod_data) || PS(mod_user_implemented)) { PS(mod)->s_close(&PS(mod_data)); - if (!EG(exception)) { - EG(exception) = old_exception; - } else if (old_exception) { - zend_exception_set_previous(EG(exception), old_exception); - } } PS(session_status) = php_session_none; return SUCCESS; diff --git a/ext/session/tests/sessionhandler_validateid_return_type.phpt b/ext/session/tests/sessionhandler_validateid_return_type.phpt deleted file mode 100644 index a100694588206..0000000000000 --- a/ext/session/tests/sessionhandler_validateid_return_type.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---TEST-- -SessionHandler::validateId must return bool ---INI-- -session.use_strict_mode=1 ---EXTENSIONS-- -session ---SKIPIF-- - ---FILE-- -getMessage(), "\n"; -} - -session_write_close(); - -try { - session_start(); -} catch (Throwable $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECTF-- -Session id must be a string diff --git a/ext/session/tests/user_session_module/session_set_save_handler_class_012.phpt b/ext/session/tests/user_session_module/session_set_save_handler_class_012.phpt index a532dff7f821a..f96206efbb647 100644 --- a/ext/session/tests/user_session_module/session_set_save_handler_class_012.phpt +++ b/ext/session/tests/user_session_module/session_set_save_handler_class_012.phpt @@ -43,8 +43,6 @@ var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i --EXPECTF-- *** Testing session_set_save_handler() : incorrect arguments for existing handler open *** Open: - -Warning: SessionHandler::close(): Parent session handler is not open in %s on line %d SessionHandler::open() expects exactly 2 arguments, 0 given Warning: Undefined global variable $_SESSION in %s on line %d From ea8aab92208186799112d1aa53dde56685332f37 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 8 Mar 2026 23:00:49 +0100 Subject: [PATCH 3/6] Fix memory leak in shm_get_var() when variable is corrupted This path wasn't tested (clearly). To trigger this we use FFI, which seemed like the easiest way that doesn't involve using another process messing with the shared memory. Closes GH-21388. --- NEWS | 3 ++ ext/sysvshm/sysvshm.c | 8 ++++-- ext/sysvshm/tests/shm_get_var_leak.phpt | 37 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 ext/sysvshm/tests/shm_get_var_leak.phpt diff --git a/NEWS b/NEWS index 5380688ce3da2..542447107face 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,9 @@ PHP NEWS . Fixed bug GH-20627 (Cannot identify some avif images with getimagesize). (y-guyon) +- Sysvshm: + . Fix memory leak in shm_get_var() when variable is corrupted. (ndossche) + 12 Mar 2026, PHP 8.4.19 - Core: diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c index 332a8b47af1b6..3fa7c77add345 100644 --- a/ext/sysvshm/sysvshm.c +++ b/ext/sysvshm/sysvshm.c @@ -309,11 +309,13 @@ PHP_FUNCTION(shm_get_var) shm_data = &shm_var->mem; PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash) != 1) { + int res = php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash); + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + if (res != 1) { php_error_docref(NULL, E_WARNING, "Variable data in shared memory is corrupted"); - RETVAL_FALSE; + zval_ptr_dtor(return_value); + RETURN_FALSE; } - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } /* }}} */ diff --git a/ext/sysvshm/tests/shm_get_var_leak.phpt b/ext/sysvshm/tests/shm_get_var_leak.phpt new file mode 100644 index 0000000000000..037bad7c41d72 --- /dev/null +++ b/ext/sysvshm/tests/shm_get_var_leak.phpt @@ -0,0 +1,37 @@ +--TEST-- +shm_get_var() leaks if variable is corrupted +--EXTENSIONS-- +sysvshm +ffi +--INI-- +ffi.enable=1 +--SKIPIF-- + +--FILE-- +shmat($ffi->shmget($key, 0, 0), $ffi->new('void *'), 0); + +$ptr[0x40 + 13] = 0; // Corrupt first byte of second element of serialized data + +var_dump(shm_get_var($s, 0)); + +shm_remove($s); + +?> +--EXPECTF-- +Warning: shm_get_var(): Variable data in shared memory is corrupted in %s on line %d +bool(false) From ae0bf447b475a367977fc432f6976536e8c9408e Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 10 Mar 2026 20:51:51 +0100 Subject: [PATCH 4/6] soap: Fix const-generic compile warning --- ext/soap/php_encoding.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 73245fd1a1818..bce33124429a9 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -2529,8 +2529,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) if (data && (attr = get_attribute(data->properties,"arrayType")) && attr->children && attr->children->content) { - const char *type; - char *end, *ns; + char *type, *end, *ns; xmlNsPtr nsptr; parse_namespace(attr->children->content, &type, &ns); From c4c1261196f7ef72ad74c0c4b3c934b6f8fb4546 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 10 Mar 2026 21:06:20 +0100 Subject: [PATCH 5/6] soap: Fix const violation --- ext/soap/php_encoding.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index bce33124429a9..f704c624875a4 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -2529,23 +2529,25 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) if (data && (attr = get_attribute(data->properties,"arrayType")) && attr->children && attr->children->content) { - char *type, *end, *ns; + const char *type; + char *end, *ns; xmlNsPtr nsptr; parse_namespace(attr->children->content, &type, &ns); + char *type_dup = estrdup(type); nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns)); - end = strrchr(type,'['); + end = strrchr(type_dup,'['); if (end) { *end = '\0'; dimension = calc_dimension(end+1); dims = get_position(dimension, end+1); } if (nsptr != NULL) { - enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type); + enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type_dup); } if (ns) {efree(ns);} - + if (type_dup) efree(type_dup); } else if ((attr = get_attribute(data->properties,"itemType")) && attr->children && attr->children->content) { From 7f2022314358841c9f18e64d065c419cffa41eb8 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 10 Mar 2026 20:13:05 +0000 Subject: [PATCH 6/6] ext/soap: use zend_string_equals_literal() instead of strcmp() (#21405) --- ext/soap/php_encoding.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 648128d9cea6e..5e3675f875bdd 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -2439,13 +2439,7 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod if (style == SOAP_ENCODED) { if (soap_version == SOAP_1_1) { smart_str_0(&array_type); -#if defined(__GNUC__) && __GNUC__ >= 11 - ZEND_DIAGNOSTIC_IGNORED_START("-Wstringop-overread") -#endif - bool is_xsd_any_type = strcmp(ZSTR_VAL(array_type.s),"xsd:anyType") == 0; -#if defined(__GNUC__) && __GNUC__ >= 11 - ZEND_DIAGNOSTIC_IGNORED_END -#endif + bool is_xsd_any_type = zend_string_equals_literal(array_type.s, "xsd:anyType"); if (is_xsd_any_type) { smart_str_free(&array_type); smart_str_appendl(&array_type,"xsd:ur-type",sizeof("xsd:ur-type")-1);