Skip to content

Commit 6441f89

Browse files
iliaaliluuu1994
authored andcommitted
Fix GH-21691: OPcache CFG optimizer drops QM_ASSIGN feeding JMPZ/JMPZ_EX with IS_VAR
The CFG optimizer (pass 5) substituted a QM_ASSIGN's source operand into its consumer without checking the source's operand type. When ASSIGN_REF produces IS_VAR and a QM_ASSIGN converts it to IS_TMP_VAR before JMPZ/JMPNZ or JMPZ_EX/JMPNZ_EX, eliminating the QM_ASSIGN leaves an IS_VAR operand on a consumer whose handler is declared CONST|TMP|CV, producing "Invalid opcode 43/4/0" (or 46/4/0 for the _EX variants). Guard both substitution sites with src->op1_type != IS_VAR, folded into the enclosing condition (per dstogov's review) so the BOOL_NOT branch is defensively covered as well. Test exercises both JMPZ and JMPZ_EX paths. Closes GH-21691 Closes GH-21696
1 parent cc8abaf commit 6441f89

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

Zend/Optimizer/block_pass.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
648648
} else if (opline->op1_type == IS_TMP_VAR &&
649649
!zend_bitset_in(used_ext, VAR_NUM(opline->op1.var))) {
650650
src = VAR_SOURCE(opline->op1);
651-
if (src) {
651+
if (src && (src->op1_type != IS_VAR)) {
652652
if (src->opcode == ZEND_BOOL_NOT) {
653653
VAR_SOURCE(opline->op1) = NULL;
654654
COPY_NODE(opline->op1, src->op1);
@@ -692,7 +692,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
692692
(!zend_bitset_in(used_ext, VAR_NUM(opline->op1.var)) ||
693693
opline->result.var == opline->op1.var)) {
694694
src = VAR_SOURCE(opline->op1);
695-
if (src) {
695+
if (src && (src->op1_type != IS_VAR)) {
696696
if (src->opcode == ZEND_BOOL ||
697697
src->opcode == ZEND_QM_ASSIGN) {
698698
VAR_SOURCE(opline->op1) = NULL;

ext/opcache/tests/gh21691.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-21691 (OPcache CFG optimizer breaks reference returns with JMPZ/JMPZ_EX)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
--EXTENSIONS--
7+
opcache
8+
--FILE--
9+
<?php
10+
11+
function &getData() {
12+
return $x;
13+
}
14+
15+
$data = &getData() && isset($data['key']);
16+
var_dump($data);
17+
18+
?>
19+
--EXPECT--
20+
NULL

0 commit comments

Comments
 (0)