1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix stale EG(opline_before_exception) pointer through eval

Fixes GH-20183
Closes GH-20184
This commit is contained in:
Ilija Tovilo
2025-10-15 21:17:43 +02:00
parent 8761c4e507
commit 12920370e1
5 changed files with 73 additions and 3 deletions

2
NEWS
View File

@@ -9,6 +9,8 @@ PHP NEWS
. Fixed bug GH-19844 (Don't bail when closing resources on shutdown). (ilutov)
. Fixed bug GH-20177 (Accessing overridden private property in
get_object_vars() triggers assertion error). (ilutov)
. Fixed bug GH-20183 (Stale EG(opline_before_exception) pointer through eval).
(ilutov)
- DOM:
. Partially fixed bug GH-16317 (DOM classes do not allow

View File

@@ -0,0 +1,24 @@
--TEST--
GH-20183: Stale EG(opline_before_exception) pointer through eval
--CREDITS--
Viet Hoang Luu (@vi3tL0u1s)
--FILE--
<?php
class A {
function __destruct() {
eval('try { throw new Error(); } catch (Error $e) {}');
debug_print_backtrace();
}
}
B::$b = new A;
?>
--EXPECTF--
#0 %s(10): A->__destruct()
Fatal error: Uncaught Error: Class "B" not found in %s:10
Stack trace:
#0 {main}
thrown in %s on line 10

View File

@@ -0,0 +1,34 @@
--TEST--
GH-20183: Stale EG(opline_before_exception) pointer through eval
--CREDITS--
Arnaud Le Blanc <lbarnaud@php.net>
--FILE--
<?php
function gen() {
try {
yield 1;
} finally {
eval('try { throw new Error(); } catch (Error) {}');
debug_print_backtrace();
}
}
class A {
private $gen;
function __construct() {
$this->gen = gen();
$this->gen->rewind();
}
}
B::$a = new A();
?>
--EXPECTF--
#0 %s(20): gen()
Fatal error: Uncaught Error: Class "B" not found in %s:20
Stack trace:
#0 {main}
thrown in %s on line 20

View File

@@ -317,9 +317,16 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[try_catch->finally_end].op1.var);
zend_generator_cleanup_unfinished_execution(generator, ex, try_catch->finally_op);
zend_object *old_exception = EG(exception);
const zend_op *old_opline_before_exception = EG(opline_before_exception);
EG(exception) = NULL;
zend_object *old_exception = NULL;
const zend_op *old_opline_before_exception = NULL;
if (EG(exception)) {
EG(current_execute_data)->opline = EG(opline_before_exception);
old_exception = EG(exception);
old_opline_before_exception = EG(opline_before_exception);
EG(exception) = NULL;
}
Z_OBJ_P(fast_call) = NULL;
Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1;
@@ -328,6 +335,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
zend_generator_resume(generator);
if (old_exception) {
EG(current_execute_data)->opline = EG(exception_op);
EG(opline_before_exception) = old_opline_before_exception;
if (EG(exception)) {
zend_exception_set_previous(EG(exception), old_exception);

View File

@@ -164,6 +164,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
&& ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) {
zend_rethrow_exception(EG(current_execute_data));
}
EG(current_execute_data)->opline = EG(opline_before_exception);
old_exception = EG(exception);
old_opline_before_exception = EG(opline_before_exception);
EG(exception) = NULL;
@@ -173,6 +174,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
zend_call_known_instance_method_with_0_params(destructor, object, NULL);
if (old_exception) {
EG(current_execute_data)->opline = EG(exception_op);
EG(opline_before_exception) = old_opline_before_exception;
if (EG(exception)) {
zend_exception_set_previous(EG(exception), old_exception);