Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <[email protected]>
--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