Skip to content
24 changes: 24 additions & 0 deletions Zend/tests/gh20183_001.phpt
Original file line number Diff line number Diff line change
@@ -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
34 changes: 34 additions & 0 deletions Zend/tests/gh20183_002.phpt
Original file line number Diff line number Diff line change
@@ -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
51 changes: 51 additions & 0 deletions Zend/tests/property_hooks/gh20270.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
--TEST--
GH-20270: Parent hook call with named arguments
--CREDITS--
Viet Hoang Luu (@vi3tL0u1s)
--FILE--
<?php

class A {
public mixed $prop1;
public mixed $prop2 {
set(mixed $custom) => $custom;
}
}

class B extends A {
public mixed $prop1 {
set {
parent::$prop1::set(value: 42);
parent::$prop1::set(unknown: 43);
}
}
public mixed $prop2 {
set {
parent::$prop2::set(custom: 42);
parent::$prop2::set(value: 43);
}
}
}

$b = new B();

try {
$b->prop1 = 0;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($b->prop1);

try {
$b->prop2 = 0;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($b->prop2);

?>
--EXPECT--
Unknown named parameter $unknown
int(42)
Unknown named parameter $value
int(42)
14 changes: 11 additions & 3 deletions Zend/zend_generators.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,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;

Expand All @@ -320,6 +327,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);
Expand Down
4 changes: 3 additions & 1 deletion Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,9 @@ ZEND_API zend_function *zend_get_property_hook_trampoline(
const zend_property_info *prop_info,
zend_property_hook_kind kind, zend_string *prop_name)
{
static const zend_arg_info arg_info[1] = {{0}};
static const zend_internal_arg_info arg_info[2] = {
{ .name = "value" }
};
zend_function *func;
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
func = &EG(trampoline);
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,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;
Expand All @@ -170,6 +171,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);
Expand Down
4 changes: 4 additions & 0 deletions ext/gd/tests/gh19955.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ GH-19955: (imagefttext() memory leak)
gd
--CREDITS--
YuanchengJiang
--SKIPIF--
<?php
if(!function_exists('imagefttext')) die('skip imagefttext() not available');
?>
--FILE--
<?php
ini_set('error_reporting', E_ALL&~E_WARNING);
Expand Down