Skip to content

Commit c9c51eb

Browse files
committedAug 22, 2022
Tracing JIT: Fix incorrect guard elimination
Fixes oss-fuzz #49917
1 parent bb34121 commit c9c51eb

File tree

2 files changed

+68
-5
lines changed

2 files changed

+68
-5
lines changed
 

‎ext/opcache/jit/zend_jit_trace.c

+43-5
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,9 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u
981981
&& (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_STRING)) {
982982
return 0;
983983
}
984+
if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
985+
return 0;
986+
}
984987
return 1;
985988
} else if (opline->opcode == ZEND_ASSIGN_OP
986989
&& (opline->extended_value == ZEND_ADD
@@ -991,18 +994,25 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u
991994
&& (tssa->var_info[tssa->ops[idx].op2_use].type & MAY_BE_REF)) {
992995
return 0;
993996
}
997+
if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
998+
return 0;
999+
}
1000+
if (opline->op2_type == IS_CONST) {
1001+
zval *zv = RT_CONSTANT(opline, opline->op2);
1002+
if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) {
1003+
return 0;
1004+
}
1005+
} else if (!(tssa->var_info[tssa->ops[idx].op2_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
1006+
return 0;
1007+
}
9941008
return 1;
9951009
}
9961010
}
9971011
if (tssa->ops[idx].result_def == var) {
9981012
const zend_op *opline = ssa_opcodes[idx];
9991013
if (opline->opcode == ZEND_ADD
10001014
|| opline->opcode == ZEND_SUB
1001-
|| opline->opcode == ZEND_MUL
1002-
|| opline->opcode == ZEND_PRE_DEC
1003-
|| opline->opcode == ZEND_PRE_INC
1004-
|| opline->opcode == ZEND_POST_DEC
1005-
|| opline->opcode == ZEND_POST_INC) {
1015+
|| opline->opcode == ZEND_MUL) {
10061016
if ((opline->op1_type & (IS_VAR|IS_CV))
10071017
&& tssa->ops[idx].op1_use >= 0
10081018
&& (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) {
@@ -1013,6 +1023,34 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u
10131023
&& (tssa->var_info[tssa->ops[idx].op2_use].type & MAY_BE_REF)) {
10141024
return 0;
10151025
}
1026+
if (opline->op1_type == IS_CONST) {
1027+
zval *zv = RT_CONSTANT(opline, opline->op1);
1028+
if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) {
1029+
return 0;
1030+
}
1031+
} else if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
1032+
return 0;
1033+
}
1034+
if (opline->op2_type == IS_CONST) {
1035+
zval *zv = RT_CONSTANT(opline, opline->op2);
1036+
if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) {
1037+
return 0;
1038+
}
1039+
} else if (!(tssa->var_info[tssa->ops[idx].op2_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
1040+
return 0;
1041+
}
1042+
} else if (opline->opcode == ZEND_PRE_DEC
1043+
|| opline->opcode == ZEND_PRE_INC
1044+
|| opline->opcode == ZEND_POST_DEC
1045+
|| opline->opcode == ZEND_POST_INC) {
1046+
if ((opline->op1_type & (IS_VAR|IS_CV))
1047+
&& tssa->ops[idx].op1_use >= 0
1048+
&& (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) {
1049+
return 0;
1050+
}
1051+
if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
1052+
return 0;
1053+
}
10161054
return 1;
10171055
}
10181056
}

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

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
JIT ADD: 014 incorrect guard elimination
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 test() {
11+
$s = null;
12+
$i = $a + $a = $j = 2;
13+
for ($a = 0; $i < 20; $a = !$a + $s .= 0xfff0001/34028236692903846346336*6) {
14+
$a = !$a + $a &= 74444444 - 444 >> 4 - $j++;
15+
if ($j > 14) break;
16+
}
17+
}
18+
try {
19+
@test();
20+
} catch (Throwable $e) {
21+
echo $e->getMessage() . "\n";
22+
}
23+
?>
24+
--EXPECT--
25+
Bit shift by negative number

0 commit comments

Comments
 (0)