Skip to content

Commit cdfd960

Browse files
committed
Fix ZEND_MATCH_ERROR misoptimization
op1 of ZEND_MATCH_ERROR, which refers to the match expression, is not freed by MATCH_ERROR itself. Instead, it is freed by ZEND_HANDLE_EXCEPTION. For normal control flow, a FREE is placed at the end of the match expression. Since FREE may appear after MATCH_ERROR in the opcode sequence, we need to correctly handle op1 of MATCH_ERROR as alive. Fixes GH-17106 Closes GH-17108
1 parent 754aa77 commit cdfd960

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-0
lines changed

NEWS

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

5+
- Core:
6+
. Fixed bug GH-17106 (ZEND_MATCH_ERROR misoptimization). (ilutov)
7+
58
- DBA:
69
. Skip test if inifile is disabled. (orlitzky)
710

Zend/Optimizer/zend_optimizer.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array,
640640
case ZEND_SWITCH_LONG:
641641
case ZEND_SWITCH_STRING:
642642
case ZEND_MATCH:
643+
case ZEND_MATCH_ERROR:
643644
case ZEND_JMP_NULL: {
644645
zend_op *end = op_array->opcodes + op_array->last;
645646
while (opline < end) {
@@ -652,6 +653,7 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array,
652653
&& opline->opcode != ZEND_SWITCH_LONG
653654
&& opline->opcode != ZEND_SWITCH_STRING
654655
&& opline->opcode != ZEND_MATCH
656+
&& opline->opcode != ZEND_MATCH_ERROR
655657
&& opline->opcode != ZEND_JMP_NULL
656658
&& (opline->opcode != ZEND_FREE
657659
|| opline->extended_value != ZEND_FREE_ON_RETURN);

Zend/zend_opcode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,7 @@ static bool keeps_op1_alive(zend_op *opline) {
877877
|| opline->opcode == ZEND_SWITCH_LONG
878878
|| opline->opcode == ZEND_SWITCH_STRING
879879
|| opline->opcode == ZEND_MATCH
880+
|| opline->opcode == ZEND_MATCH_ERROR
880881
|| opline->opcode == ZEND_FETCH_LIST_R
881882
|| opline->opcode == ZEND_FETCH_LIST_W
882883
|| opline->opcode == ZEND_COPY_TMP) {

ext/opcache/tests/gh17106.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-17106: ZEND_MATCH_ERROR misoptimization
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable_cli=1
7+
opcache.optimization_level=-1
8+
--FILE--
9+
<?php
10+
11+
const X = 2;
12+
13+
var_dump(7 ?? match (X) {});
14+
var_dump(null ?? match (X) { 2 => 2 });
15+
var_dump(match (X) { 2 => 2 });
16+
17+
?>
18+
--EXPECT--
19+
int(7)
20+
int(2)
21+
int(2)

0 commit comments

Comments
 (0)