Skip to content

Commit 567213c

Browse files
committed
Drop range inference for IS_NULL/IS_FALSE/IS_TRUE.
These values not always converted to IS_LONG (e.g. by -- and ++) and this leads to incorrect range inferene and later to incorrect JIT code generation.
1 parent e10d2c2 commit 567213c

File tree

6 files changed

+93
-70
lines changed

6 files changed

+93
-70
lines changed

Zend/Optimizer/zend_inference.c

+1-55
Original file line numberDiff line numberDiff line change
@@ -1017,15 +1017,6 @@ static bool zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *s
10171017
}
10181018
return (tmp->min <= tmp->max);
10191019
} else if (ssa->vars[var].definition < 0) {
1020-
if (var < op_array->last_var &&
1021-
op_array->function_name) {
1022-
1023-
tmp->min = 0;
1024-
tmp->max = 0;
1025-
tmp->underflow = 0;
1026-
tmp->overflow = 0;
1027-
return 1;
1028-
}
10291020
return 0;
10301021
}
10311022
line = ssa->vars[var].definition;
@@ -4199,52 +4190,7 @@ static void zend_func_return_info(const zend_op_array *op_array,
41994190
if (opline->op1_type == IS_CONST) {
42004191
zval *zv = CRT_CONSTANT(opline->op1);
42014192

4202-
if (Z_TYPE_P(zv) == IS_NULL) {
4203-
if (tmp_has_range < 0) {
4204-
tmp_has_range = 1;
4205-
tmp_range.underflow = 0;
4206-
tmp_range.min = 0;
4207-
tmp_range.max = 0;
4208-
tmp_range.overflow = 0;
4209-
} else if (tmp_has_range) {
4210-
if (!tmp_range.underflow) {
4211-
tmp_range.min = MIN(tmp_range.min, 0);
4212-
}
4213-
if (!tmp_range.overflow) {
4214-
tmp_range.max = MAX(tmp_range.max, 0);
4215-
}
4216-
}
4217-
} else if (Z_TYPE_P(zv) == IS_FALSE) {
4218-
if (tmp_has_range < 0) {
4219-
tmp_has_range = 1;
4220-
tmp_range.underflow = 0;
4221-
tmp_range.min = 0;
4222-
tmp_range.max = 0;
4223-
tmp_range.overflow = 0;
4224-
} else if (tmp_has_range) {
4225-
if (!tmp_range.underflow) {
4226-
tmp_range.min = MIN(tmp_range.min, 0);
4227-
}
4228-
if (!tmp_range.overflow) {
4229-
tmp_range.max = MAX(tmp_range.max, 0);
4230-
}
4231-
}
4232-
} else if (Z_TYPE_P(zv) == IS_TRUE) {
4233-
if (tmp_has_range < 0) {
4234-
tmp_has_range = 1;
4235-
tmp_range.underflow = 0;
4236-
tmp_range.min = 1;
4237-
tmp_range.max = 1;
4238-
tmp_range.overflow = 0;
4239-
} else if (tmp_has_range) {
4240-
if (!tmp_range.underflow) {
4241-
tmp_range.min = MIN(tmp_range.min, 1);
4242-
}
4243-
if (!tmp_range.overflow) {
4244-
tmp_range.max = MAX(tmp_range.max, 1);
4245-
}
4246-
}
4247-
} else if (Z_TYPE_P(zv) == IS_LONG) {
4193+
if (Z_TYPE_P(zv) == IS_LONG) {
42484194
if (tmp_has_range < 0) {
42494195
tmp_has_range = 1;
42504196
tmp_range.underflow = 0;

Zend/Optimizer/zend_inference.h

+3-15
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
{ \
4141
if (opline->opN##_type == IS_CONST) { \
4242
zval *zv = CRT_CONSTANT(opline->opN); \
43-
return (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE || Z_TYPE_P(zv) == IS_NULL); \
43+
return (Z_TYPE_P(zv) == IS_LONG); \
4444
} else { \
4545
return (opline->opN##_type != IS_UNUSED && \
4646
ssa->var_info && \
@@ -57,12 +57,6 @@
5757
zval *zv = CRT_CONSTANT(opline->opN); \
5858
if (Z_TYPE_P(zv) == IS_LONG) { \
5959
return Z_LVAL_P(zv); \
60-
} else if (Z_TYPE_P(zv) == IS_TRUE) { \
61-
return 1; \
62-
} else if (Z_TYPE_P(zv) == IS_FALSE) { \
63-
return 0; \
64-
} else if (Z_TYPE_P(zv) == IS_NULL) { \
65-
return 0; \
6660
} \
6761
} else if (opline->opN##_type != IS_UNUSED && \
6862
ssa->var_info && \
@@ -80,12 +74,6 @@
8074
zval *zv = CRT_CONSTANT(opline->opN); \
8175
if (Z_TYPE_P(zv) == IS_LONG) { \
8276
return Z_LVAL_P(zv); \
83-
} else if (Z_TYPE_P(zv) == IS_TRUE) { \
84-
return 1; \
85-
} else if (Z_TYPE_P(zv) == IS_FALSE) { \
86-
return 0; \
87-
} else if (Z_TYPE_P(zv) == IS_NULL) { \
88-
return 0; \
8977
} \
9078
} else if (opline->opN##_type != IS_UNUSED && \
9179
ssa->var_info && \
@@ -101,7 +89,7 @@
10189
{ \
10290
if (opline->opN##_type == IS_CONST) { \
10391
zval *zv = CRT_CONSTANT(opline->opN); \
104-
if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE || Z_TYPE_P(zv) == IS_NULL) { \
92+
if (Z_TYPE_P(zv) == IS_LONG) { \
10593
return 0; \
10694
} \
10795
} else if (opline->opN##_type != IS_UNUSED && \
@@ -118,7 +106,7 @@
118106
{ \
119107
if (opline->opN##_type == IS_CONST) { \
120108
zval *zv = CRT_CONSTANT(opline->opN); \
121-
if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE || Z_TYPE_P(zv) == IS_NULL) { \
109+
if (Z_TYPE_P(zv) == IS_LONG) { \
122110
return 0; \
123111
} \
124112
} else if (opline->opN##_type != IS_UNUSED && \
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Range inference 016:
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--FILE--
8+
<?php
9+
function test() {
10+
$a = $y = null;
11+
for(;;$a-- + $a % $a = $y + $a) {
12+
var_dump($a);
13+
}
14+
}
15+
try {
16+
@test();
17+
} catch (Throwable $e) {
18+
echo $e->getMessage(), "\n";
19+
}
20+
?>
21+
--EXPECT--
22+
NULL
23+
Modulo by zero
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Range inference 017:
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--FILE--
8+
<?php
9+
function test() {
10+
for(;;) {
11+
$a = $a-- + 0 / $a;
12+
}
13+
}
14+
try {
15+
@test();
16+
} catch (Throwable $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
?>
20+
--EXPECT--
21+
Division by zero
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Range inference 018:
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--FILE--
8+
<?php
9+
function test() {
10+
for(;;) {
11+
$a--;
12+
$a &= $a / $a;
13+
$a--;
14+
}
15+
}
16+
try {
17+
@test();
18+
} catch (Throwable $e) {
19+
echo $e->getMessage(), "\n";
20+
}
21+
?>
22+
--EXPECT--
23+
Division by zero
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Range inference 019:
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--FILE--
8+
<?php
9+
function test() {
10+
$a = $y = null;
11+
for($cnt = 0; $cnt < 6; $cnt++) {
12+
$e = $a-- + $a *= $a;
13+
$a-- + $y -= $e;
14+
$a-- + $a *= $a;
15+
$a-- + $a *= $a;
16+
}
17+
}
18+
test();
19+
?>
20+
DONE
21+
--EXPECT--
22+
DONE

0 commit comments

Comments
 (0)