1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00
Files
archived-php-src/ext/opcache/tests/jit/gh21267_blacklist.phpt
Ilia Alshanetsky e1a3a4c9a4 Fix GH-21267: JIT infinite loop on FETCH_OBJ_R with IS_UNDEF property (#21368)
When the JIT defers the IS_UNDEF check for FETCH_OBJ_R to the result
type guard, the deoptimization escape path dispatches to opline->handler
via the trace_escape stub. If opline->handler has been overwritten with
JIT code (e.g. a function entry trace), this creates an infinite loop.

Fix by dispatching to the original VM handler (orig_handler from the
trace extension) instead of going through the trace_escape stub. This
avoids the extra IS_UNDEF guard on every property read while correctly
handling the rare IS_UNDEF case during deoptimization.

Also set current_op_array in zend_jit_trace_exit_to_vm so that the
blacklisted exit deoptimizer can resolve orig_handler, covering the
case where side trace compilation is exhausted.

Closes GH-21368.
2026-03-16 21:31:49 +03:00

37 lines
662 B
PHP

--TEST--
GH-21267 (JIT infinite loop on FETCH_OBJ_R with IS_UNDEF via blacklisted trace exit)
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=tracing
opcache.jit_buffer_size=64M
opcache.jit_hot_loop=0
opcache.jit_hot_func=2
opcache.jit_hot_return=0
opcache.jit_hot_side_exit=1
opcache.jit_max_side_traces=0
--FILE--
<?php
class C {
public $x = true;
public function __get($name) { return null; }
public function getX() { return $this->x; }
}
$o1 = new C;
$o2 = new C;
$o2->x = false;
$o3 = new C;
unset($o3->x);
$a = [$o1, $o2, $o3];
for ($i = 0; $i < 8; $i++) {
$m = $a[$i % 3];
$m->getX();
$m->getX();
}
?>
OK
--EXPECT--
OK