summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-02-15 14:58:59 +0100
committerNikita Popov <nikita.ppv@gmail.com>2021-02-15 14:58:59 +0100
commit882862563a8281457afb9c5ad93763605e295270 (patch)
treebf7ecee1ad2a4de1db5c858c404ce05e73e95f40
parentc70220205e20005ad916289ea6958d156fac54da (diff)
parent7b7d99839c2e2886ecf159952552c9964bd80481 (diff)
downloadphp-git-882862563a8281457afb9c5ad93763605e295270.tar.gz
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix symtable cache being used while cleaning symtable
-rw-r--r--Zend/tests/symtable_cache_recursive_dtor.phpt19
-rw-r--r--Zend/zend_execute.c7
2 files changed, 23 insertions, 3 deletions
diff --git a/Zend/tests/symtable_cache_recursive_dtor.phpt b/Zend/tests/symtable_cache_recursive_dtor.phpt
new file mode 100644
index 0000000000..def0816a66
--- /dev/null
+++ b/Zend/tests/symtable_cache_recursive_dtor.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Symtable cache slots may be acquired while cleaning symtable
+--FILE--
+<?php
+class A {
+ // Must be larger than the symtable cache.
+ static $max = 40;
+ function __destruct() {
+ if (self::$max-- < 0) return;
+ $x = 'y';
+ $$x = new a;
+ }
+}
+new A;
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index bc964c1ad1..edf6c61794 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -3396,12 +3396,13 @@ ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_val
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
{
+ /* Clean before putting into the cache, since clean could call dtors,
+ * which could use the cached hash. Also do this before the check for
+ * available cache slots, as those may be used by a dtor as well. */
+ zend_symtable_clean(symbol_table);
if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
zend_array_destroy(symbol_table);
} else {
- /* clean before putting into the cache, since clean
- could call dtors, which could use cached hash */
- zend_symtable_clean(symbol_table);
*(EG(symtable_cache_ptr)++) = symbol_table;
}
}