Skip to content

Commit ddc5a62

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix GH-24391: JIT: switch on constant null takes default instead of case 0
2 parents 0694e58 + 1fb0b45 commit ddc5a62

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
@@ -65,6 +65,8 @@ PHP NEWS
6565
. Fix SIGFPE on LONG_MIN % -1 with a constant divisor. (waroad)
6666
. Fixed bug GH-24388 (Tracing JIT: segfault when a trace runs out of side
6767
exits). (Lazizbek Ergashev)
68+
. Fixed bug GH-24391 (JIT switch on constant null takes default instead of
69+
case 0). (ndossche)
6870

6971
- PDO:
7072
. 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
@@ -16250,15 +16250,22 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1625016250
if (opline->op1_type == IS_CONST) {
1625116251
zval *zv = RT_CONSTANT(opline, opline->op1);
1625216252
zval *jump_zv = NULL;
16253+
const zend_op *target;
1625316254
int b;
1625416255

16256+
/* Wrong type for SWITCH_LONG/SWITCH_STRING falls back to the ZEND_CASE chain */
16257+
target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
1625516258
if (opline->opcode == ZEND_SWITCH_LONG) {
1625616259
if (Z_TYPE_P(zv) == IS_LONG) {
1625716260
jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(zv));
16261+
} else {
16262+
target = opline + 1;
1625816263
}
1625916264
} else if (opline->opcode == ZEND_SWITCH_STRING) {
1626016265
if (Z_TYPE_P(zv) == IS_STRING) {
1626116266
jump_zv = zend_hash_find_known_hash(jumptable, Z_STR_P(zv));
16267+
} else {
16268+
target = opline + 1;
1626216269
}
1626316270
} else if (opline->opcode == ZEND_MATCH) {
1626416271
if (Z_TYPE_P(zv) == IS_LONG) {
@@ -16269,21 +16276,13 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1626916276
} else {
1627016277
ZEND_UNREACHABLE();
1627116278
}
16279+
if (jump_zv != NULL) {
16280+
target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(jump_zv));
16281+
}
1627216282
if (next_opline) {
16273-
const zend_op *target;
16274-
16275-
if (jump_zv != NULL) {
16276-
target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(jump_zv));
16277-
} else {
16278-
target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
16279-
}
1628016283
ZEND_ASSERT(target == next_opline);
1628116284
} else {
16282-
if (jump_zv != NULL) {
16283-
b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(jump_zv)) - op_array->opcodes];
16284-
} else {
16285-
b = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) - op_array->opcodes];
16286-
}
16285+
b = ssa->cfg.map[target - op_array->opcodes];
1628716286
_zend_jit_add_predecessor_ref(jit, b, jit->b, ir_END());
1628816287
jit->b = -1;
1628916288
}

‎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)