From c3acfb1b57f4375ca1d8e78161c89785d5ad855c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:26:16 +0200 Subject: [PATCH] Fix GH-13931: Applying zero offset to null pointer in Zend/zend_opcode.c In the test cases, the compiler bails out due to a fatal error. The data structures used by the compiler will contain stale values. In particular, for the test case CG(loop_var_stack) will contain data. The next compilation will incorrectly use elements from the previous stack. To solve this, we reset part of the compiler data structures. We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. Closes GH-13938. --- NEWS | 2 ++ Zend/tests/gh13931.phpt | 23 +++++++++++++++++++++++ main/main.c | 8 ++++++++ sapi/phpdbg/tests/gh13931.phpt | 21 +++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 Zend/tests/gh13931.phpt create mode 100644 sapi/phpdbg/tests/gh13931.phpt diff --git a/NEWS b/NEWS index cd339a91b16..f9664526c9a 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug GH-13772 (Invalid execute_data->opline pointers in observer fcall handlers when JIT is enabled). (Bob) + . Fixed bug GH-13931 (Applying zero offset to null pointer in + Zend/zend_opcode.c). (nielsdos) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). diff --git a/Zend/tests/gh13931.phpt b/Zend/tests/gh13931.phpt new file mode 100644 index 00000000000..5f2873b449f --- /dev/null +++ b/Zend/tests/gh13931.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-13931 (Applying zero offset to null pointer in Zend/zend_opcode.c) +--FILE-- + +--EXPECTF-- +Fatal error: 'break' not in the 'loop' or 'switch' context in %s on line %d +int(4) diff --git a/main/main.c b/main/main.c index 83f8829890e..634b00936bc 100644 --- a/main/main.c +++ b/main/main.c @@ -1405,6 +1405,14 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c /* restore memory limit */ zend_set_memory_limit(PG(memory_limit)); zend_objects_store_mark_destructed(&EG(objects_store)); + if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) { + /* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack). + * If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state, + * otherwise this will lead to incorrect compilation during shutdown. + * We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */ + shutdown_compiler(); + zend_init_compiler_data_structures(); + } zend_bailout(); return; } diff --git a/sapi/phpdbg/tests/gh13931.phpt b/sapi/phpdbg/tests/gh13931.phpt new file mode 100644 index 00000000000..25520435feb --- /dev/null +++ b/sapi/phpdbg/tests/gh13931.phpt @@ -0,0 +1,21 @@ +--TEST-- +Applying zero offset to null pointer in Zend/zend_opcode.c +--FILE-- + +--PHPDBG-- +ev 1 + 3 +ev 2 ** 3 +q +--EXPECTF-- +Fatal error: 'break' not in the 'loop' or 'switch' context in %s on line %d +prompt> 4 +prompt> 8 +prompt>