From 495d7cbb2ed63d8f4115c002b7f14fb6db0dd809 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 28 Oct 2026 06:27:30 +0000 Subject: [PATCH] Fix GH-24445: Tracing JIT loses register-allocated CVs in catch blocks. Should also fix GH-24798 --- ext/opcache/jit/zend_jit_trace.c | 9 ++++++++ ext/opcache/tests/jit/gh24445.phpt | 36 ++++++++++++++++++++++++++++++ ext/opcache/tests/jit/gh24798.phpt | 33 +++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 ext/opcache/tests/jit/gh24445.phpt create mode 100644 ext/opcache/tests/jit/gh24798.phpt diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index b424934e4927..0656ef252740 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3266,6 +3266,15 @@ static zend_jit_reg_var* zend_jit_trace_allocate_registers(zend_jit_trace_rec *t } if (count) { + for (i = 0; i < ssa->vars_count; i++) { + if (RA_HAS_REG(i) && + vars_op_array[i] && + vars_op_array[i]->last_try_catch && + ssa->vars[i].var < vars_op_array[i]->last_var && + !(RA_REG_FLAGS(i) & ZREG_LOAD)) { + RA_REG_FLAGS(i) |= ZREG_STORE; + } + } /* SSA resolution */ if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL diff --git a/ext/opcache/tests/jit/gh24445.phpt b/ext/opcache/tests/jit/gh24445.phpt new file mode 100644 index 000000000000..e858855ec2c1 --- /dev/null +++ b/ext/opcache/tests/jit/gh24445.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-24445 (Tracing JIT: a catch reads an int local as undefined after an internal call throws) +--CREDITS-- +EJ-Research +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=tracing +opcache.jit_hot_loop=1 +opcache.jit_hot_func=1 +--FILE-- + +--EXPECT-- +int(1) diff --git a/ext/opcache/tests/jit/gh24798.phpt b/ext/opcache/tests/jit/gh24798.phpt new file mode 100644 index 000000000000..b0fd253de038 --- /dev/null +++ b/ext/opcache/tests/jit/gh24798.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-24798 (Tracing JIT loses register-allocated CVs when an exception is caught in the same function) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=tracing +opcache.jit_hot_loop=1 +opcache.jit_hot_func=1 +opcache.jit_hot_return=1 +opcache.jit_hot_side_exit=1 +--FILE-- +getMessage(), ' at $i = ', $i, PHP_EOL; + $s += 100; + } + } + return $s; +} +var_dump(f(5)); +?> +--EXPECT-- +DivisionByZeroError: Division by zero at $i = 2 +float(100)