Skip to content
Open
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
8 changes: 8 additions & 0 deletions ext/opcache/jit/zend_jit_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,14 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
// TODO: recompilation may change target ???
return 0;
#endif
case ZEND_FETCH_OBJ_R:
if (opline->op2_type == IS_CONST) {
const zend_class_entry *ce = opline->op1_type == IS_UNUSED ? op_array->scope : NULL;
if (!ce || !(ce->ce_flags & ZEND_ACC_FINAL) || ce->num_hooked_props > 0) {
return 1;
}
}
break;
case ZEND_RETURN_BY_REF:
case ZEND_RETURN:
/* return */
Expand Down
37 changes: 37 additions & 0 deletions ext/opcache/tests/jit/gh20890.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
GH-20890 (Segfault in zval_undefined_cv with non-simple property hook with minimal tracing JIT)
--CREDITS--
Moonster8282
--EXTENSIONS--
opcache
--INI--
opcache.jit=1251
--FILE--
<?php
class HookJIT {
private int $readCount = 0;

public int $computed {
get {
$this->readCount++;
return $this->readCount * 2;
}
}
}

function hook_hot_path($obj, $iterations) {
$sum = 0;
for ($i = 0; $i < $iterations; $i++) {
$sum += $obj->computed;
}
return $sum;
}

echo "Testing property hook in hot path...\n";
$obj = new HookJIT();
$result = hook_hot_path($obj, 100);
echo "Result: $result\n";
?>
--EXPECT--
Testing property hook in hot path...
Result: 10100
Loading