Skip to content

Commit d4946a5

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Fix stale EG(opline_before_exception) pointer through eval
2 parents 932241f + 1a74e9b commit d4946a5

File tree

4 files changed

+71
-3
lines changed

4 files changed

+71
-3
lines changed

Zend/tests/gh20183_001.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-20183: Stale EG(opline_before_exception) pointer through eval
3+
--CREDITS--
4+
Viet Hoang Luu (@vi3tL0u1s)
5+
--FILE--
6+
<?php
7+
8+
class A {
9+
function __destruct() {
10+
eval('try { throw new Error(); } catch (Error $e) {}');
11+
debug_print_backtrace();
12+
}
13+
}
14+
15+
B::$b = new A;
16+
17+
?>
18+
--EXPECTF--
19+
#0 %s(10): A->__destruct()
20+
21+
Fatal error: Uncaught Error: Class "B" not found in %s:10
22+
Stack trace:
23+
#0 {main}
24+
thrown in %s on line 10

Zend/tests/gh20183_002.phpt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
GH-20183: Stale EG(opline_before_exception) pointer through eval
3+
--CREDITS--
4+
Arnaud Le Blanc <[email protected]>
5+
--FILE--
6+
<?php
7+
8+
function gen() {
9+
try {
10+
yield 1;
11+
} finally {
12+
eval('try { throw new Error(); } catch (Error) {}');
13+
debug_print_backtrace();
14+
}
15+
}
16+
17+
class A {
18+
private $gen;
19+
function __construct() {
20+
$this->gen = gen();
21+
$this->gen->rewind();
22+
}
23+
}
24+
25+
B::$a = new A();
26+
27+
?>
28+
--EXPECTF--
29+
#0 %s(20): gen()
30+
31+
Fatal error: Uncaught Error: Class "B" not found in %s:20
32+
Stack trace:
33+
#0 {main}
34+
thrown in %s on line 20

Zend/zend_generators.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,16 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
308308
ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[try_catch->finally_end].op1.var);
309309

310310
zend_generator_cleanup_unfinished_execution(generator, ex, try_catch->finally_op);
311-
zend_object *old_exception = EG(exception);
312-
const zend_op *old_opline_before_exception = EG(opline_before_exception);
313-
EG(exception) = NULL;
311+
312+
zend_object *old_exception = NULL;
313+
const zend_op *old_opline_before_exception = NULL;
314+
if (EG(exception)) {
315+
EG(current_execute_data)->opline = EG(opline_before_exception);
316+
old_exception = EG(exception);
317+
old_opline_before_exception = EG(opline_before_exception);
318+
EG(exception) = NULL;
319+
}
320+
314321
Z_OBJ_P(fast_call) = NULL;
315322
Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1;
316323

@@ -320,6 +327,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
320327
zend_generator_resume(generator);
321328

322329
if (old_exception) {
330+
EG(current_execute_data)->opline = EG(exception_op);
323331
EG(opline_before_exception) = old_opline_before_exception;
324332
if (EG(exception)) {
325333
zend_exception_set_previous(EG(exception), old_exception);

Zend/zend_objects.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
161161
&& ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) {
162162
zend_rethrow_exception(EG(current_execute_data));
163163
}
164+
EG(current_execute_data)->opline = EG(opline_before_exception);
164165
old_exception = EG(exception);
165166
old_opline_before_exception = EG(opline_before_exception);
166167
EG(exception) = NULL;
@@ -170,6 +171,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
170171
zend_call_known_instance_method_with_0_params(destructor, object, NULL);
171172

172173
if (old_exception) {
174+
EG(current_execute_data)->opline = EG(exception_op);
173175
EG(opline_before_exception) = old_opline_before_exception;
174176
if (EG(exception)) {
175177
zend_exception_set_previous(EG(exception), old_exception);

0 commit comments

Comments
 (0)