Skip to content

Commit 6f42c07

Browse files
committed
Remove range inference for booleans.
Range inference for bolleans and longs comparison was incorrect. Fizes oss-fuzz #fuzz-42161.php
1 parent 5675ebe commit 6f42c07

File tree

3 files changed

+28
-163
lines changed

3 files changed

+28
-163
lines changed

ext/opcache/Optimizer/zend_inference.c

+2-155
Original file line numberDiff line numberDiff line change
@@ -996,8 +996,6 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
996996

997997
int zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, zend_ssa_op* ssa_op, int var, zend_ssa_range *tmp)
998998
{
999-
zend_long op1_min, op2_min, op1_max, op2_max;
1000-
1001999
tmp->underflow = 0;
10021000
tmp->overflow = 0;
10031001
switch (opline->opcode) {
@@ -1025,8 +1023,8 @@ int zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa,
10251023
tmp->min = ZEND_LONG_MIN;
10261024
tmp->max = ZEND_LONG_MAX;
10271025
} else {
1028-
op1_min = OP1_MIN_RANGE();
1029-
op1_max = OP1_MAX_RANGE();
1026+
zend_long op1_min = OP1_MIN_RANGE();
1027+
zend_long op1_max = OP1_MAX_RANGE();
10301028
tmp->min = ~op1_max;
10311029
tmp->max = ~op1_min;
10321030
}
@@ -1059,144 +1057,6 @@ int zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa,
10591057
}
10601058
}
10611059
break;
1062-
case ZEND_BOOL:
1063-
case ZEND_JMPZ_EX:
1064-
case ZEND_JMPNZ_EX:
1065-
if (ssa_op->result_def == var) {
1066-
if (OP1_HAS_RANGE()) {
1067-
op1_min = OP1_MIN_RANGE();
1068-
op1_max = OP1_MAX_RANGE();
1069-
tmp->min = (op1_min > 0 || op1_max < 0);
1070-
tmp->max = (op1_min != 0 || op1_max != 0);
1071-
return 1;
1072-
} else {
1073-
tmp->min = 0;
1074-
tmp->max = 1;
1075-
return 1;
1076-
}
1077-
}
1078-
break;
1079-
case ZEND_BOOL_NOT:
1080-
if (ssa_op->result_def == var) {
1081-
if (OP1_HAS_RANGE()) {
1082-
op1_min = OP1_MIN_RANGE();
1083-
op1_max = OP1_MAX_RANGE();
1084-
tmp->min = (op1_min == 0 && op1_max == 0);
1085-
tmp->max = (op1_min <= 0 && op1_max >= 0);
1086-
return 1;
1087-
} else {
1088-
tmp->min = 0;
1089-
tmp->max = 1;
1090-
return 1;
1091-
}
1092-
}
1093-
break;
1094-
case ZEND_BOOL_XOR:
1095-
if (ssa_op->result_def == var) {
1096-
if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1097-
op1_min = OP1_MIN_RANGE();
1098-
op2_min = OP2_MIN_RANGE();
1099-
op1_max = OP1_MAX_RANGE();
1100-
op2_max = OP2_MAX_RANGE();
1101-
op1_min = (op1_min > 0 || op1_max < 0);
1102-
op1_max = (op1_min != 0 || op1_max != 0);
1103-
op2_min = (op2_min > 0 || op2_max < 0);
1104-
op2_max = (op2_min != 0 || op2_max != 0);
1105-
tmp->min = 0;
1106-
tmp->max = 1;
1107-
if (op1_min == op1_max && op2_min == op2_max) {
1108-
if (op1_min == op2_min) {
1109-
tmp->max = 0;
1110-
} else {
1111-
tmp->min = 1;
1112-
}
1113-
}
1114-
return 1;
1115-
} else {
1116-
tmp->min = 0;
1117-
tmp->max = 1;
1118-
return 1;
1119-
}
1120-
}
1121-
break;
1122-
case ZEND_IS_IDENTICAL:
1123-
case ZEND_IS_EQUAL:
1124-
if (ssa_op->result_def == var) {
1125-
if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1126-
op1_min = OP1_MIN_RANGE();
1127-
op2_min = OP2_MIN_RANGE();
1128-
op1_max = OP1_MAX_RANGE();
1129-
op2_max = OP2_MAX_RANGE();
1130-
1131-
tmp->min = (op1_min == op1_max &&
1132-
op2_min == op2_max &&
1133-
op1_min == op2_max);
1134-
tmp->max = (op1_min <= op2_max && op1_max >= op2_min);
1135-
return 1;
1136-
} else {
1137-
tmp->min = 0;
1138-
tmp->max = 1;
1139-
return 1;
1140-
}
1141-
}
1142-
break;
1143-
case ZEND_IS_NOT_IDENTICAL:
1144-
case ZEND_IS_NOT_EQUAL:
1145-
if (ssa_op->result_def == var) {
1146-
if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1147-
op1_min = OP1_MIN_RANGE();
1148-
op2_min = OP2_MIN_RANGE();
1149-
op1_max = OP1_MAX_RANGE();
1150-
op2_max = OP2_MAX_RANGE();
1151-
1152-
tmp->min = (op1_min > op2_max || op1_max < op2_min);
1153-
tmp->max = (op1_min != op1_max ||
1154-
op2_min != op2_max ||
1155-
op1_min != op2_max);
1156-
return 1;
1157-
} else {
1158-
tmp->min = 0;
1159-
tmp->max = 1;
1160-
return 1;
1161-
}
1162-
}
1163-
break;
1164-
case ZEND_IS_SMALLER:
1165-
if (ssa_op->result_def == var) {
1166-
if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1167-
op1_min = OP1_MIN_RANGE();
1168-
op2_min = OP2_MIN_RANGE();
1169-
op1_max = OP1_MAX_RANGE();
1170-
op2_max = OP2_MAX_RANGE();
1171-
1172-
tmp->min = op1_max < op2_min;
1173-
tmp->max = op1_min < op2_max;
1174-
return 1;
1175-
} else {
1176-
tmp->min = 0;
1177-
tmp->max = 1;
1178-
return 1;
1179-
}
1180-
}
1181-
break;
1182-
case ZEND_IS_SMALLER_OR_EQUAL:
1183-
if (ssa_op->result_def == var) {
1184-
if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1185-
op1_min = OP1_MIN_RANGE();
1186-
op2_min = OP2_MIN_RANGE();
1187-
op1_max = OP1_MAX_RANGE();
1188-
op2_max = OP2_MAX_RANGE();
1189-
1190-
tmp->min = op1_max <= op2_min;
1191-
tmp->max = op1_min <= op2_max;
1192-
return 1;
1193-
} else {
1194-
tmp->min = 0;
1195-
tmp->max = 1;
1196-
return 1;
1197-
}
1198-
}
1199-
break;
12001060
case ZEND_QM_ASSIGN:
12011061
case ZEND_JMP_SET:
12021062
case ZEND_COALESCE:
@@ -1222,13 +1082,6 @@ int zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa,
12221082
}
12231083
}
12241084
break;
1225-
case ZEND_ASSERT_CHECK:
1226-
if (ssa_op->result_def == var) {
1227-
tmp->min = 0;
1228-
tmp->max = 1;
1229-
return 1;
1230-
}
1231-
break;
12321085
case ZEND_SEND_VAR:
12331086
if (ssa_op->op1_def == var) {
12341087
if (ssa_op->op1_def >= 0) {
@@ -1409,12 +1262,6 @@ int zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa,
14091262
tmp->max = ZEND_LONG_MAX;
14101263
tmp->overflow = 0;
14111264
return 1;
1412-
} else if (mask == MAY_BE_BOOL) {
1413-
tmp->underflow = 0;
1414-
tmp->min = 0;
1415-
tmp->max = 1;
1416-
tmp->overflow = 0;
1417-
return 1;
14181265
}
14191266
}
14201267
}

ext/opcache/Optimizer/zend_ssa.c

-8
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,6 @@ static void place_essa_pis(
335335

336336
if (Z_TYPE_P(zv) == IS_LONG) {
337337
add_val2 = Z_LVAL_P(zv);
338-
} else if (Z_TYPE_P(zv) == IS_FALSE) {
339-
add_val2 = 0;
340-
} else if (Z_TYPE_P(zv) == IS_TRUE) {
341-
add_val2 = 1;
342338
} else {
343339
var1 = -1;
344340
}
@@ -356,10 +352,6 @@ static void place_essa_pis(
356352
zval *zv = CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1);
357353
if (Z_TYPE_P(zv) == IS_LONG) {
358354
add_val1 = Z_LVAL_P(CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1));
359-
} else if (Z_TYPE_P(zv) == IS_FALSE) {
360-
add_val1 = 0;
361-
} else if (Z_TYPE_P(zv) == IS_TRUE) {
362-
add_val1 = 1;
363355
} else {
364356
var2 = -1;
365357
}

ext/opcache/tests/jit/cmp_008.phpt

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
JIT CMP: 008 Wrong range inference for comparison between IS_LONG and IS_FALSE/IS_TRUE
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
opcache.protect_memory=1
9+
--FILE--
10+
<?php
11+
function test() {
12+
for ($i = 0; $i < 10; $i %= -4 != -4 < ($a = $a + $a)) {
13+
}
14+
}
15+
test();
16+
?>
17+
--EXPECTF--
18+
Warning: Undefined variable $a in %scmp_008.php on line 3
19+
20+
Warning: Undefined variable $a in %scmp_008.php on line 3
21+
22+
Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %scmp_008.php:3
23+
Stack trace:
24+
#0 %scmp_008.php(6): test()
25+
#1 {main}
26+
thrown in %scmp_008.php on line 3

0 commit comments

Comments
 (0)