Skip to content

Commit 8fc3615

Browse files
committed
Fixed compilation of "switch" with undefined input
Fixes oss-fuzz #63559
1 parent 3a8767b commit 8fc3615

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

ext/opcache/jit/zend_jit_ir.c

+24-12
Original file line numberDiff line numberDiff line change
@@ -15166,18 +15166,10 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1516615166
int b;
1516715167
int32_t exit_point;
1516815168
const void *exit_addr;
15169-
const void *fallback_label = NULL;
1517015169
const void *default_label = NULL;
1517115170
zval *zv;
1517215171

1517315172
if (next_opline) {
15174-
if (opline->opcode != ZEND_MATCH && next_opline != opline + 1) {
15175-
exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
15176-
fallback_label = zend_jit_trace_get_exit_addr(exit_point);
15177-
if (!fallback_label) {
15178-
return 0;
15179-
}
15180-
}
1518115173
if (next_opline != default_opline) {
1518215174
exit_point = zend_jit_trace_get_exit_point(default_opline, 0);
1518315175
default_label = zend_jit_trace_get_exit_addr(exit_point);
@@ -15189,6 +15181,17 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1518915181

1519015182
if (opline->opcode == ZEND_SWITCH_LONG) {
1519115183
if (op1_info & MAY_BE_LONG) {
15184+
const void *fallback_label = NULL;
15185+
15186+
if (next_opline) {
15187+
if (next_opline != opline + 1) {
15188+
exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
15189+
fallback_label = zend_jit_trace_get_exit_addr(exit_point);
15190+
if (!fallback_label) {
15191+
return 0;
15192+
}
15193+
}
15194+
}
1519215195
if (op1_info & MAY_BE_REF) {
1519315196
ir_ref ref, if_long, fast_path, ref2;
1519415197

@@ -15294,13 +15297,23 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1529415297
}
1529515298
jit->b = -1;
1529615299
}
15297-
} else {
15298-
ZEND_ASSERT(!next_opline);
15300+
} else if (!next_opline) {
1529915301
_zend_jit_add_predecessor_ref(jit, jit->b + 1, jit->b, ir_END());
1530015302
jit->b = -1;
1530115303
}
1530215304
} else if (opline->opcode == ZEND_SWITCH_STRING) {
1530315305
if (op1_info & MAY_BE_STRING) {
15306+
const void *fallback_label = NULL;
15307+
15308+
if (next_opline) {
15309+
if (next_opline != opline + 1) {
15310+
exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
15311+
fallback_label = zend_jit_trace_get_exit_addr(exit_point);
15312+
if (!fallback_label) {
15313+
return 0;
15314+
}
15315+
}
15316+
}
1530415317
if (op1_info & MAY_BE_REF) {
1530515318
ir_ref ref, if_string, fast_path, ref2;
1530615319

@@ -15403,8 +15416,7 @@ static int zend_jit_switch(zend_jit_ctx *jit, const zend_op *opline, const zend_
1540315416
}
1540415417
jit->b = -1;
1540515418
}
15406-
} else {
15407-
ZEND_ASSERT(!next_opline);
15419+
} else if (!next_opline) {
1540815420
_zend_jit_add_predecessor_ref(jit, jit->b + 1, jit->b, ir_END());
1540915421
jit->b = -1;
1541015422
}

ext/opcache/tests/jit/switch_001.phpt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Switch with undefined input
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
--FILE--
9+
<?php
10+
function foo() {
11+
switch($y) {
12+
case 'x':
13+
case 'y':
14+
}
15+
}
16+
foo();
17+
?>
18+
DONE
19+
--EXPECTF--
20+
Warning: Undefined variable $y in %sswitch_001.php on line 4
21+
22+
Warning: Undefined variable $y in %sswitch_001.php on line 5
23+
DONE

0 commit comments

Comments
 (0)