Skip to content

Commit b18303f

Browse files
committed
Fix GH-17428: Assertion failure ext/opcache/jit/zend_jit_ir.c:8940
The code to update the call_level in that case skips the opline itself, as that's handled by the tail handler, and then wants to set the opline to the last opline of the block because the code below the switch will update the call_level for that opline. However, the test has a block with a single opline (THROW). The block after that has ZEND_INIT_FCALL, because `i` points to ZEND_INIT_FCALL now, it erroneously causes the call_level after the switch. Although it suffices to change `i` to `end` (none of the opcodes here occur in `zend_jit_dec_call_level`), I added a goto label as well to be safer for the future in case the list of opcodes changes.
1 parent 27fbdc1 commit b18303f

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,8 +2633,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
26332633
call_level--;
26342634
}
26352635
}
2636-
opline = op_array->opcodes + i;
2637-
break;
2636+
opline = op_array->opcodes + end;
2637+
goto done_no_dec_call_level;
26382638
/* stackless execution */
26392639
case ZEND_INCLUDE_OR_EVAL:
26402640
case ZEND_DO_FCALL:
@@ -2727,6 +2727,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
27272727
if (zend_jit_dec_call_level(opline->opcode)) {
27282728
call_level--;
27292729
}
2730+
done_no_dec_call_level:
27302731
}
27312732
zend_jit_bb_end(&ctx, b);
27322733
}

ext/opcache/tests/jit/gh17428.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GH-17428 (Assertion failure ext/opcache/jit/zend_jit_ir.c:8940)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.jit=1205
7+
--FILE--
8+
<?php
9+
new EmptyIterator();
10+
srand(1000);
11+
error_reporting(E_ALL);
12+
testConversion('', '');
13+
testConversion('', '');
14+
testConversion('', '');
15+
testConversion('', '');
16+
testConversion('', '');
17+
function testRoundTrip($data) {
18+
}
19+
for ($iterations = 0; $iterations < 100; $iterations++) {
20+
$strlen = rand(1, 100);
21+
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
22+
$randstring = '';
23+
for ($i = 0; $i < $strlen; $i++) {
24+
$randstring .= $characters[rand(0, strlen($characters) - 1)];
25+
}
26+
die($randstring);
27+
}
28+
echo "Done!\n";
29+
throw new Hello(new stdClass);
30+
?>
31+
--EXPECTF--
32+
Fatal error: Uncaught Error: Call to undefined function testConversion() in %s:%d
33+
Stack trace:
34+
#0 {main}
35+
thrown in %s on line %d

0 commit comments

Comments
 (0)