Skip to content

Commit 57c62eb

Browse files
committed
Fix GH-20890: Segfault in zval_undefined_cv with non-simple property hook with minimal tracing JIT
This is similar to f6c2e40 but for minimal JIT + tracing JIT. Most of the times the tracing JIT shouldn't rely on going to the VM, but in some cases, like in minimal JIT, it can and then it hits the same bug. Closes GH-20897.
1 parent 6a21a41 commit 57c62eb

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ PHP NEWS
2525
. Fixed bug GH-20836 (Stack overflow in mb_convert_variables with
2626
recursive array references). (alexandre-daubois)
2727

28+
- Opcache:
29+
. Fixed bug GH-20890 (Segfault in zval_undefined_cv with non-simple
30+
property hook with minimal tracing JIT). (ndossche)
31+
2832
- Phar:
2933
. Fixed bug GH-20882 (buildFromIterator breaks with missing base directory).
3034
(ndossche)

ext/opcache/jit/zend_jit_trace.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
328328
// TODO: recompilation may change target ???
329329
return 0;
330330
#endif
331+
case ZEND_FETCH_OBJ_R:
332+
if (opline->op2_type == IS_CONST) {
333+
const zend_class_entry *ce = opline->op1_type == IS_UNUSED ? op_array->scope : NULL;
334+
if (!ce || !(ce->ce_flags & ZEND_ACC_FINAL) || ce->num_hooked_props > 0) {
335+
return 1;
336+
}
337+
}
338+
break;
331339
case ZEND_RETURN_BY_REF:
332340
case ZEND_RETURN:
333341
/* return */

ext/opcache/tests/jit/gh20890.phpt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
GH-20890 (Segfault in zval_undefined_cv with non-simple property hook with minimal tracing JIT)
3+
--CREDITS--
4+
Moonster8282
5+
--EXTENSIONS--
6+
opcache
7+
--INI--
8+
opcache.jit=1251
9+
--FILE--
10+
<?php
11+
class HookJIT {
12+
private int $readCount = 0;
13+
14+
public int $computed {
15+
get {
16+
$this->readCount++;
17+
return $this->readCount * 2;
18+
}
19+
}
20+
}
21+
22+
function hook_hot_path($obj, $iterations) {
23+
$sum = 0;
24+
for ($i = 0; $i < $iterations; $i++) {
25+
$sum += $obj->computed;
26+
}
27+
return $sum;
28+
}
29+
30+
echo "Testing property hook in hot path...\n";
31+
$obj = new HookJIT();
32+
$result = hook_hot_path($obj, 100);
33+
echo "Result: $result\n";
34+
?>
35+
--EXPECT--
36+
Testing property hook in hot path...
37+
Result: 10100

0 commit comments

Comments
 (0)