From 3a7a0f93b3916b7e9e4d3fdc9d1421e2e76ecd14 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 24 Jun 2024 21:18:23 +0100 Subject: [PATCH 1/4] Fix GH-14643 ext/standard: segfault on user shutdown function release. --- ext/standard/basic_functions.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index fee800f7e0263..df34ea32600ad 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1582,9 +1582,12 @@ static void fci_release(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) void user_shutdown_function_dtor(zval *zv) /* {{{ */ { php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv); + zend_fcall_info *fci = &shutdown_function_entry->fci; - zend_fcall_info_args_clear(&shutdown_function_entry->fci, true); - fci_release(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache); + if (fci) { + zend_fcall_info_args_clear(fci, true); + fci_release(fci, &shutdown_function_entry->fci_cache); + } efree(shutdown_function_entry); } /* }}} */ From 313913fdd1628c3a24209b23ab315809c86f15b4 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 25 Jun 2024 13:06:43 +0100 Subject: [PATCH 2/4] add test --- ext/standard/tests/gh14643_longname.phpt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 ext/standard/tests/gh14643_longname.phpt diff --git a/ext/standard/tests/gh14643_longname.phpt b/ext/standard/tests/gh14643_longname.phpt new file mode 100644 index 0000000000000..c0fac9d805da6 --- /dev/null +++ b/ext/standard/tests/gh14643_longname.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-14643: Segfault on empty user function. +--FILE-- +flush(); +register_shutdown_function([$this, 'flush'], true); +}); +} +public function flush($final = false) { +} +} +for ($i = 0; $i < 200; $script1_dataflow++) { +$a = new Logger(); +} +var_fusion($script1_connect, $script2_connect, $random_var); +?> +--EXPECTF-- +Fatal error: Allowed memory size of %d bytes exhausted %s + +Fatal error: Allowed memory size of %d bytes exhausted %s From 85ca7a9f1700ec2ffd99a03fb42137becac8c21d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 25 Jun 2024 19:54:28 +0100 Subject: [PATCH 3/4] changes from feedback --- Zend/zend_hash.h | 15 ++++++++------- ext/standard/basic_functions.c | 7 ++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index d4385d162a0fc..cd2caf7f3bb44 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -851,15 +851,16 @@ static zend_always_inline void *zend_hash_index_update_mem(HashTable *ht, zend_u static zend_always_inline void *zend_hash_next_index_insert_mem(HashTable *ht, void *pData, size_t size) { - zval tmp, *zv; + zval tmp; - ZVAL_PTR(&tmp, NULL); - if ((zv = zend_hash_next_index_insert(ht, &tmp))) { - Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); - memcpy(Z_PTR_P(zv), pData, size); - return Z_PTR_P(zv); + void *p = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); + memcpy(p, pData, size); + ZVAL_PTR(&tmp, p); + if (!zend_hash_next_index_insert(ht, &tmp)) { + pefree(p, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); + return NULL; } - return NULL; + return p; } static zend_always_inline void *zend_hash_find_ptr(const HashTable *ht, zend_string *key) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index df34ea32600ad..fee800f7e0263 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1582,12 +1582,9 @@ static void fci_release(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) void user_shutdown_function_dtor(zval *zv) /* {{{ */ { php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv); - zend_fcall_info *fci = &shutdown_function_entry->fci; - if (fci) { - zend_fcall_info_args_clear(fci, true); - fci_release(fci, &shutdown_function_entry->fci_cache); - } + zend_fcall_info_args_clear(&shutdown_function_entry->fci, true); + fci_release(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache); efree(shutdown_function_entry); } /* }}} */ From 4e4ec32f1748fc3a3d4f06f289aa94579618f4b2 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 25 Jun 2024 20:40:41 +0100 Subject: [PATCH 4/4] update test --- ext/standard/tests/gh14643_longname.phpt | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/ext/standard/tests/gh14643_longname.phpt b/ext/standard/tests/gh14643_longname.phpt index c0fac9d805da6..6062a99556165 100644 --- a/ext/standard/tests/gh14643_longname.phpt +++ b/ext/standard/tests/gh14643_longname.phpt @@ -2,21 +2,19 @@ GH-14643: Segfault on empty user function. --FILE-- flush(); -register_shutdown_function([$this, 'flush'], true); -}); + public function __construct() { + register_shutdown_function(function () { + $this->flush(); + register_shutdown_function([$this, 'flush'], true); + }); + } + public function flush($final = false) { + } } -public function flush($final = false) { +while (true) { + $a = new Logger(); } -} -for ($i = 0; $i < 200; $script1_dataflow++) { -$a = new Logger(); -} -var_fusion($script1_connect, $script2_connect, $random_var); ?> --EXPECTF-- Fatal error: Allowed memory size of %d bytes exhausted %s