Skip to content

Commit af098ac

Browse files
committed
Always load EX(opline) into the current frame in JIT when observers are enabled
Fixes #13772. Closes #13776.
1 parent 85d6212 commit af098ac

File tree

5 files changed

+52
-2
lines changed

5 files changed

+52
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.19
44

5+
- Core:
6+
. Fixed bug GH-13772 (Invalid execute_data->opline pointers in observer fcall
7+
handlers when JIT is enabled). (Bob)
8+
59
- FPM:
610
. Fixed bug GH-13563 (Setting bool values via env in FPM config fails).
711
(Jakub Zelenka)

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9449,7 +9449,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
94499449
}
94509450

94519451
if (ZEND_OBSERVER_ENABLED) {
9452-
| SAVE_IP
9452+
if (trace && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) {
9453+
ZEND_ASSERT(trace[1].op == ZEND_JIT_TRACE_VM || trace[1].op == ZEND_JIT_TRACE_END);
9454+
| SET_EX_OPLINE trace[1].opline, REG0
9455+
} else {
9456+
| SAVE_IP
9457+
}
94539458
| mov FCARG1x, FP
94549459
| EXT_CALL zend_observer_fcall_begin, REG0
94559460
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10187,7 +10187,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
1018710187
}
1018810188

1018910189
if (ZEND_OBSERVER_ENABLED) {
10190-
| SAVE_IP
10190+
if (trace && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) {
10191+
ZEND_ASSERT(trace[1].op == ZEND_JIT_TRACE_VM || trace[1].op == ZEND_JIT_TRACE_END);
10192+
| SET_EX_OPLINE trace[1].opline, r0
10193+
} else {
10194+
| SAVE_IP
10195+
}
1019110196
| mov FCARG1a, FP
1019210197
| EXT_CALL zend_observer_fcall_begin, r0
1019310198
}

ext/opcache/tests/jit/gh13772.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
EX(opline) is correctly set for nested JIT user code calls
3+
--EXTENSIONS--
4+
opcache
5+
zend_test
6+
--INI--
7+
opcache.enable=1
8+
opcache.enable_cli=1
9+
zend_test.observer.enabled=1
10+
zend_test.observer.observe_all=1
11+
zend_test.observer.show_output=0
12+
--FILE--
13+
<?php
14+
15+
function Ack($m, $n) {
16+
if ($m == 0) return $n+1;
17+
if ($n == 0) return Ack($m-1, 1);
18+
return Ack($m - 1, Ack($m, ($n - 1)));
19+
}
20+
21+
var_dump(Ack(3, 3));
22+
23+
?>
24+
--EXPECT--
25+
int(61)
26+

ext/zend_test/observer.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,16 @@ static void observer_show_opcode(zend_execute_data *execute_data)
6767
php_printf("%*s<!-- opcode: '%s' -->\n", 2 * ZT_G(observer_nesting_depth), "", zend_get_opcode_name(EX(opline)->opcode));
6868
}
6969

70+
static inline void assert_observer_opline(zend_execute_data *execute_data) {
71+
ZEND_ASSERT(!ZEND_USER_CODE(EX(func)->type) ||
72+
(EX(opline) >= EX(func)->op_array.opcodes && EX(opline) < EX(func)->op_array.opcodes + EX(func)->op_array.last) ||
73+
(EX(opline) >= EG(exception_op) && EX(opline) < EG(exception_op) + 3));
74+
}
75+
7076
static void observer_begin(zend_execute_data *execute_data)
7177
{
78+
assert_observer_opline(execute_data);
79+
7280
if (!ZT_G(observer_show_output)) {
7381
return;
7482
}
@@ -112,6 +120,8 @@ static void get_retval_info(zval *retval, smart_str *buf)
112120

113121
static void observer_end(zend_execute_data *execute_data, zval *retval)
114122
{
123+
assert_observer_opline(execute_data);
124+
115125
if (!ZT_G(observer_show_output)) {
116126
return;
117127
}

0 commit comments

Comments
 (0)