From 7b7d99839c2e2886ecf159952552c9964bd80481 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 15 Feb 2021 14:52:38 +0100 Subject: [PATCH] Fix symtable cache being used while cleaning symtable We need to first clean the symtable and then check whether a cache slot is available for it. Otherwise, it may happen that a destructor runs while cleaning the table and uses up all the remaining slots in the cache. This is particularly insidious because once we overflow the cache, the first pointer we modify is symtable_cache_ptr, making it hard to understand what happened after the fact. Fixes oss-fuzz #30815. --- Zend/tests/symtable_cache_recursive_dtor.phpt | 19 +++++++++++++++++++ Zend/zend_execute.c | 7 ++++--- 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/symtable_cache_recursive_dtor.phpt 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-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index b6839bb88b..f58b1131ba 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3437,12 +3437,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; } } -- 2.40.0