Skip to content

Commit 90f1c24

Browse files
committed
Fix GH-21691: OPcache CFG optimizer eliminates QM_ASSIGN feeding JMPZ with VAR operand
The CFG optimizer (pass 5) removed a QM_ASSIGN that converted IS_VAR to IS_TMP_VAR before JMPZ. JMPZ has no handler for IS_VAR operands, producing "Invalid opcode 43/4/0." This occurred when ASSIGN_REF (which produces IS_VAR) fed into a conditional via QM_ASSIGN. Skip the QM_ASSIGN elimination when the source operand is IS_VAR. Closes GH-21691
1 parent 57d6d71 commit 90f1c24

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

Zend/Optimizer/block_pass.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,9 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
714714
continue;
715715
} else if (src->opcode == ZEND_BOOL ||
716716
src->opcode == ZEND_QM_ASSIGN) {
717+
if (src->op1_type == IS_VAR) {
718+
break;
719+
}
717720
VAR_SOURCE(opline->op1) = NULL;
718721
COPY_NODE(opline->op1, src->op1);
719722
MAKE_NOP(src);

ext/opcache/tests/gh21691.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-21691 (OPcache CFG optimizer breaks reference returns with JMPZ)
3+
--INI--
4+
opcache.enable_cli=1
5+
--EXTENSIONS--
6+
opcache
7+
--FILE--
8+
<?php
9+
class Base {
10+
protected function &getData(): array {
11+
$x = [];
12+
return $x;
13+
}
14+
15+
public function process(): array {
16+
if ($data = &$this->getData() && !isset($data['key'])) {
17+
}
18+
return $data;
19+
}
20+
}
21+
22+
class Child extends Base {
23+
protected function &getData(): array {
24+
static $x = ['value' => 42];
25+
return $x;
26+
}
27+
}
28+
29+
$child = new Child();
30+
var_dump($child->process());
31+
?>
32+
--EXPECT--
33+
array(1) {
34+
["value"]=>
35+
int(42)
36+
}

0 commit comments

Comments
 (0)