Skip to content

Commit 6978b51

Browse files
committed
1 parent 842f4c7 commit 6978b51

24 files changed

+285
-98
lines changed

Zend/Optimizer/block_pass.c

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -436,21 +436,14 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
436436
Tsource[VAR_NUM(opline->op1.var)] = NULL;
437437
break;
438438
}
439-
ZEND_FALLTHROUGH;
440-
441-
case ZEND_IS_EQUAL:
442-
case ZEND_IS_NOT_EQUAL:
443439
if (opline->op1_type == IS_CONST &&
444-
opline->op2_type == IS_CONST) {
440+
opline->op2_type == IS_CONST) {
445441
goto optimize_constant_binary_op;
446-
}
447-
/* IS_EQ(TRUE, X) => BOOL(X)
448-
* IS_EQ(FALSE, X) => BOOL_NOT(X)
449-
* IS_NOT_EQ(TRUE, X) => BOOL_NOT(X)
450-
* IS_NOT_EQ(FALSE, X) => BOOL(X)
451-
* CASE(TRUE, X) => BOOL(X)
452-
* CASE(FALSE, X) => BOOL_NOT(X)
453-
*/
442+
}
443+
/*
444+
* CASE(TRUE, X) => BOOL(X)
445+
* CASE(FALSE, X) => BOOL_NOT(X)
446+
*/
454447
if (opline->op1_type == IS_CONST &&
455448
(Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_FALSE ||
456449
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_TRUE)) {
@@ -464,19 +457,34 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
464457
SET_UNUSED(opline->op2);
465458
++(*opt_count);
466459
goto optimize_bool;
467-
} else if (opline->op2_type == IS_CONST &&
468-
(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_FALSE ||
469-
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_TRUE)) {
470-
/* Optimization of comparison with "null" is not safe,
471-
* because ("0" == null) is not equal to !("0")
472-
*/
473-
opline->opcode =
474-
((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP2_LITERAL(opline))) == IS_TRUE)) ?
475-
ZEND_BOOL : ZEND_BOOL_NOT;
476-
SET_UNUSED(opline->op2);
477-
++(*opt_count);
478-
goto optimize_bool;
460+
} else if (opline->op2_type == IS_CONST &&
461+
(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_FALSE ||
462+
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_TRUE)) {
463+
/* Optimization of comparison with "null" is not safe,
464+
* because ("0" == null) is not equal to !("0")
465+
*/
466+
opline->opcode =
467+
((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP2_LITERAL(opline))) == IS_TRUE)) ?
468+
ZEND_BOOL : ZEND_BOOL_NOT;
469+
SET_UNUSED(opline->op2);
470+
++(*opt_count);
471+
goto optimize_bool;
472+
}
473+
break;
474+
475+
case ZEND_IS_EQUAL:
476+
case ZEND_IS_NOT_EQUAL:
477+
if (opline->op1_type == IS_CONST &&
478+
opline->op2_type == IS_CONST) {
479+
goto optimize_constant_binary_op;
479480
}
481+
/* IS_EQ(TRUE, X) => BOOL(X)
482+
* IS_EQ(FALSE, X) => BOOL_NOT(X)
483+
* IS_NOT_EQ(TRUE, X) => BOOL_NOT(X)
484+
* IS_NOT_EQ(FALSE, X) => BOOL(X)
485+
* Those optimizations are not safe if the other operand end up being NAN
486+
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not.
487+
*/
480488
break;
481489
case ZEND_IS_IDENTICAL:
482490
if (opline->op1_type == IS_CONST &&

Zend/Optimizer/sccp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ static inline zend_result ct_eval_bool_cast(zval *result, zval *op) {
335335
ZVAL_TRUE(result);
336336
return SUCCESS;
337337
}
338+
/* NAN warns when casting */
339+
if (Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op))) {
340+
return FAILURE;
341+
}
338342

339343
ZVAL_BOOL(result, zend_is_true(op));
340344
return SUCCESS;

Zend/Optimizer/zend_inference.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5109,14 +5109,16 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
51095109
case ZEND_PRE_DEC:
51105110
case ZEND_POST_DEC:
51115111
return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5112-
case ZEND_BOOL_NOT:
51135112
case ZEND_JMPZ:
51145113
case ZEND_JMPNZ:
51155114
case ZEND_JMPZ_EX:
51165115
case ZEND_JMPNZ_EX:
5117-
case ZEND_BOOL:
51185116
case ZEND_JMP_SET:
51195117
return (t1 & MAY_BE_OBJECT);
5118+
case ZEND_BOOL:
5119+
case ZEND_BOOL_NOT:
5120+
/* NAN Cast to bool will warn */
5121+
return (t1 & MAY_BE_OBJECT) || (t1 & MAY_BE_DOUBLE);
51205122
case ZEND_BOOL_XOR:
51215123
return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_OBJECT);
51225124
case ZEND_IS_EQUAL:

Zend/Optimizer/zend_optimizer.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ zend_result zend_optimizer_eval_unary_op(zval *result, uint8_t opcode, zval *op1
7474
}
7575
return unary_op(result, op1);
7676
} else { /* ZEND_BOOL */
77+
if (Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1))) {
78+
return FAILURE;
79+
}
7780
ZVAL_BOOL(result, zend_is_true(op1));
7881
return SUCCESS;
7982
}

Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn_32bit.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Explicit (int) cast must not warn 32bit variation
2+
Explicit (int) cast must not warn if value is representable 32bit variation
33
--SKIPIF--
44
<?php
55
if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");

Zend/tests/type_coercion/float_to_int/union_int_string_type_arg.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ int(1)
2323

2424
Deprecated: Implicit conversion from float 1.5 to int loses precision in %s on line %d
2525
int(1)
26+
27+
Warning: unexpected NAN value was coerced to string in %s on line %d
2628
string(3) "NAN"
2729
string(8) "1.0E+121"
2830
string(3) "INF"

Zend/tests/type_coercion/nan_to_other.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,53 @@ foreach ($types as $type) {
4040
?>
4141
--EXPECTF--
4242
float(NAN)
43+
44+
Warning: unexpected NAN value was coerced to bool in %s on line %d
4345
bool(true)
46+
47+
Warning: unexpected NAN value was coerced to string in %s on line %d
4448
string(3) "NAN"
49+
50+
Warning: unexpected NAN value was coerced to int in %s on line %d
4551
int(0)
52+
53+
Warning: unexpected NAN value was coerced to bool in %s on line %d
4654
bool(true)
55+
56+
Warning: unexpected NAN value was coerced to string in %s on line %d
4757
string(3) "NAN"
58+
59+
Warning: unexpected NAN value was coerced to array in %s on line %d
4860
array(1) {
4961
[0]=>
5062
float(NAN)
5163
}
64+
65+
Warning: unexpected NAN value was coerced to object in %s on line %d
5266
object(stdClass)#%d (1) {
5367
["scalar"]=>
5468
float(NAN)
5569
}
70+
71+
Warning: unexpected NAN value was coerced to null in %s on line %d
5672
NULL
73+
74+
Warning: unexpected NAN value was coerced to bool in %s on line %d
5775
bool(true)
76+
77+
Warning: unexpected NAN value was coerced to int in %s on line %d
5878
int(0)
79+
80+
Warning: unexpected NAN value was coerced to string in %s on line %d
5981
string(3) "NAN"
82+
83+
Warning: unexpected NAN value was coerced to array in %s on line %d
6084
array(1) {
6185
[0]=>
6286
float(NAN)
6387
}
88+
89+
Warning: unexpected NAN value was coerced to object in %s on line %d
6490
object(stdClass)#%d (1) {
6591
["scalar"]=>
6692
float(NAN)

Zend/tests/type_declarations/scalar_basic.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ string(0) ""
194194
string(%d) "%d"
195195

196196
*** Trying float(NAN)
197+
E_WARNING: unexpected NAN value was coerced to string on line %d
197198
string(3) "NAN"
198199

199200
*** Trying bool(true)
@@ -247,6 +248,7 @@ bool(false)
247248
bool(true)
248249

249250
*** Trying float(NAN)
251+
E_WARNING: unexpected NAN value was coerced to bool on line %d
250252
bool(true)
251253

252254
*** Trying bool(true)

Zend/tests/type_declarations/scalar_return_basic.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ string(0) ""
156156
*** Trying int(2147483647)
157157
string(10) "2147483647"
158158
*** Trying float(NAN)
159+
E_WARNING: unexpected NAN value was coerced to string on line %d
159160
string(3) "NAN"
160161
*** Trying bool(true)
161162
string(1) "1"
@@ -193,6 +194,7 @@ bool(false)
193194
*** Trying int(2147483647)
194195
bool(true)
195196
*** Trying float(NAN)
197+
E_WARNING: unexpected NAN value was coerced to bool on line %d
196198
bool(true)
197199
*** Trying bool(true)
198200
bool(true)

Zend/tests/type_declarations/scalar_return_basic_64bit.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ string(0) ""
156156
*** Trying int(9223372036854775807)
157157
string(19) "9223372036854775807"
158158
*** Trying float(NAN)
159+
E_WARNING: unexpected NAN value was coerced to string on line %d
159160
string(3) "NAN"
160161
*** Trying bool(true)
161162
string(1) "1"
@@ -193,6 +194,7 @@ bool(false)
193194
*** Trying int(9223372036854775807)
194195
bool(true)
195196
*** Trying float(NAN)
197+
E_WARNING: unexpected NAN value was coerced to bool on line %d
196198
bool(true)
197199
*** Trying bool(true)
198200
bool(true)

0 commit comments

Comments
 (0)