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.
This commit is contained in:
Niels Dossche 2024-04-10 20:26:16 +02:00
parent 5f9b9c4e23
commit c3acfb1b57
No known key found for this signature in database
GPG key ID: B8A8AD166DF0E2E5
4 changed files with 54 additions and 0 deletions

2
NEWS
View file

@ -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()).

23
Zend/tests/gh13931.phpt Normal file
View file

@ -0,0 +1,23 @@
--TEST--
GH-13931 (Applying zero offset to null pointer in Zend/zend_opcode.c)
--FILE--
<?php
register_shutdown_function(function() {
var_dump(eval("return 1+3;"));
});
eval(<<<EVAL
function foo () {
try {
break;
} finally {
}
}
foo();
EVAL);
?>
--EXPECTF--
Fatal error: 'break' not in the 'loop' or 'switch' context in %s on line %d
int(4)

View file

@ -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;
}

View file

@ -0,0 +1,21 @@
--TEST--
Applying zero offset to null pointer in Zend/zend_opcode.c
--FILE--
<?php
function foo () {
try {
break;
} finally {
}
}
foo();
?>
--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>