Skip to content

Commit 91281f8

Browse files
committed
Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5: Fix GH-24391: JIT: switch on constant null takes default instead of case 0
2 parents a4b3811 + ddc5a62 commit 91281f8

3 files changed

Lines changed: 50 additions & 12 deletions

File tree

‎NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ PHP NEWS
6161
. Fix SIGFPE on LONG_MIN % -1 with a constant divisor. (waroad)
6262
. Fixed bug GH-24388 (Tracing JIT: segfault when a trace runs out of side
6363
exits). (Lazizbek Ergashev)
64+
. Fixed bug GH-24391 (JIT switch on constant null takes default instead of
65+
case 0). (ndossche)
6466

6567
- PDO:
6668
. Fixed a duplicate warning when ATTR_STATEMENT_CLASS is rejected on a

‎ext/opcache/jit/zend_jit_ir.c‎

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16301,15 +16301,22 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1630116301
if (opline->op1_type == IS_CONST) {
1630216302
zval *zv = RT_CONSTANT(opline, opline->op1);
1630316303
zval *jump_zv = NULL;
16304+
const zend_op *target;
1630416305
int b;
1630516306

16307+
/* Wrong type for SWITCH_LONG/SWITCH_STRING falls back to the ZEND_CASE chain */
16308+
target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
1630616309
if (opline->opcode == ZEND_SWITCH_LONG) {
1630716310
if (Z_TYPE_P(zv) == IS_LONG) {
1630816311
jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(zv));
16312+
} else {
16313+
target = opline + 1;
1630916314
}
1631016315
} else if (opline->opcode == ZEND_SWITCH_STRING) {
1631116316
if (Z_TYPE_P(zv) == IS_STRING) {
1631216317
jump_zv = zend_hash_find_known_hash(jumptable, Z_STR_P(zv));
16318+
} else {
16319+
target = opline + 1;
1631316320
}
1631416321
} else if (opline->opcode == ZEND_MATCH) {
1631516322
if (Z_TYPE_P(zv) == IS_LONG) {
@@ -16320,21 +16327,13 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1632016327
} else {
1632116328
ZEND_UNREACHABLE();
1632216329
}
16330+
if (jump_zv != NULL) {
16331+
target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(jump_zv));
16332+
}
1632316333
if (next_opline) {
16324-
const zend_op *target;
16325-
16326-
if (jump_zv != NULL) {
16327-
target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(jump_zv));
16328-
} else {
16329-
target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
16330-
}
1633116334
ZEND_ASSERT(target == next_opline);
1633216335
} else {
16333-
if (jump_zv != NULL) {
16334-
b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(jump_zv)) - op_array->opcodes];
16335-
} else {
16336-
b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) - op_array->opcodes];
16337-
}
16336+
b = ssa->cfg.map[target - op_array->opcodes];
1633816337
_zend_jit_add_predecessor_ref(jit, b, jit->b, ir_END());
1633916338
jit->b = -1;
1634016339
}

‎ext/opcache/tests/jit/gh24391.phpt‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
GH-24391 (JIT: switch on constant of wrong type takes default instead of falling back to the case chain)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit=function
9+
opcache.optimization_level=0
10+
--FILE--
11+
<?php
12+
function long_switch() {
13+
switch (null) {
14+
case 0: return 1;
15+
case 1: return 2;
16+
case 2: return 3;
17+
case 3: return 4;
18+
case 4: return 5;
19+
default: return 6;
20+
}
21+
}
22+
23+
function string_switch() {
24+
switch (0) {
25+
case "aa": return 1;
26+
case "bb": return 2;
27+
case "cc": return 3;
28+
default: return 6;
29+
}
30+
}
31+
32+
var_dump(long_switch());
33+
var_dump(string_switch());
34+
?>
35+
--EXPECT--
36+
int(1)
37+
int(6)

0 commit comments

Comments
 (0)