Skip to content

Commit 525bbef

Browse files
committed
1 parent d9088cf commit 525bbef

18 files changed

+197
-84
lines changed

Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn.phpt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Explicit (int) cast must not warn
2+
Explicit (int) cast must not warn (except for NAN)
33
--SKIPIF--
44
<?php
55
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
@@ -12,12 +12,10 @@ $values =[
1212
3.5,
1313
10e120,
1414
10e300,
15-
fdiv(0, 0),
1615
(string) 3.0,
1716
(string) 3.5,
1817
(string) 10e120,
1918
(string) 10e300,
20-
(string) fdiv(0, 0),
2119
];
2220

2321
foreach($values as $value) {
@@ -30,9 +28,7 @@ int(3)
3028
int(3)
3129
int(0)
3230
int(0)
33-
int(0)
3431
int(3)
3532
int(3)
3633
int(9223372036854775807)
3734
int(9223372036854775807)
38-
int(0)

Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn_32bit.phpt

Lines changed: 1 addition & 5 deletions
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 (except for NAN) 32bit variation
33
--SKIPIF--
44
<?php
55
if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
@@ -12,12 +12,10 @@ $values =[
1212
3.5,
1313
10e120,
1414
10e300,
15-
fdiv(0, 0),
1615
(string) 3.0,
1716
(string) 3.5,
1817
(string) 10e120,
1918
(string) 10e300,
20-
(string) fdiv(0, 0),
2119
];
2220

2321
foreach($values as $value) {
@@ -30,9 +28,7 @@ int(3)
3028
int(3)
3129
int(0)
3230
int(0)
33-
int(0)
3431
int(3)
3532
int(3)
3633
int(2147483647)
3734
int(2147483647)
38-
int(0)

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/int_special_values.phpt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ $values = [
88
-INF,
99
1 / INF,
1010
-1 / INF, // Negative zero,
11-
NAN
1211
];
1312

1413
foreach($values as $value) {
@@ -32,6 +31,3 @@ int(0)
3231

3332
float(-0)
3433
int(0)
35-
36-
float(NAN)
37-
int(0)

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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ string(0) ""
156156
*** Trying int(2147483647)
157157
string(10) "2147483647"
158158
*** Trying float(NAN)
159-
string(3) "NAN"
159+
E_WARNING: unexpected NAN value was coerced to string on line %d
160160
*** Trying bool(true)
161161
string(1) "1"
162162
*** Trying bool(false)
@@ -193,6 +193,7 @@ bool(false)
193193
*** Trying int(2147483647)
194194
bool(true)
195195
*** Trying float(NAN)
196+
E_WARNING: unexpected NAN value was coerced to bool on line %d
196197
bool(true)
197198
*** Trying bool(true)
198199
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)

Zend/zend_compile.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10181,6 +10181,7 @@ static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
1018110181
}
1018210182

1018310183
do {
10184+
// TODO do not do this for NAN?
1018410185
if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
1018510186
if (left_node.op_type == IS_CONST) {
1018610187
if (Z_TYPE(left_node.u.constant) == IS_FALSE) {

Zend/zend_operators.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,9 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
669669

670670
ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */
671671
{
672+
if (UNEXPECTED(Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op)))) {
673+
zend_nan_coerced_to_type_warning(IS_NULL);
674+
}
672675
zval_ptr_dtor(op);
673676
ZVAL_NULL(op);
674677
}
@@ -697,6 +700,9 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
697700
ZVAL_BOOL(op, Z_LVAL_P(op) ? 1 : 0);
698701
break;
699702
case IS_DOUBLE:
703+
if (UNEXPECTED(zend_isnan(Z_DVAL_P(op)))) {
704+
zend_nan_coerced_to_type_warning(_IS_BOOL);
705+
}
700706
ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0);
701707
break;
702708
case IS_STRING:
@@ -810,6 +816,9 @@ ZEND_API bool ZEND_FASTCALL _try_convert_to_string(zval *op) /* {{{ */
810816

811817
static void convert_scalar_to_array(zval *op) /* {{{ */
812818
{
819+
if (UNEXPECTED(Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op)))) {
820+
zend_nan_coerced_to_type_warning(IS_ARRAY);
821+
}
813822
HashTable *ht = zend_new_array(1);
814823
zend_hash_index_add_new(ht, 0, op);
815824
ZVAL_ARR(op, ht);
@@ -892,6 +901,11 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
892901
case IS_REFERENCE:
893902
zend_unwrap_reference(op);
894903
goto try_again;
904+
case IS_DOUBLE:
905+
if (UNEXPECTED(zend_isnan(Z_DVAL_P(op)))) {
906+
zend_nan_coerced_to_type_warning(IS_OBJECT);
907+
}
908+
ZEND_FALLTHROUGH;
895909
default: {
896910
zval tmp;
897911
ZVAL_COPY_VALUE(&tmp, op);
@@ -912,6 +926,11 @@ ZEND_API void ZEND_COLD zend_incompatible_string_to_long_error(const zend_string
912926
zend_error(E_DEPRECATED, "Implicit conversion from float-string \"%s\" to int loses precision", ZSTR_VAL(s));
913927
}
914928

929+
ZEND_API void ZEND_COLD zend_nan_coerced_to_type_warning(uint8_t type)
930+
{
931+
zend_error(E_WARNING, "unexpected NAN value was coerced to %s", zend_get_type_by_const(type));
932+
}
933+
915934
ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_strict) /* {{{ */
916935
{
917936
try_again:
@@ -2246,6 +2265,8 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
22462265
double str_dval;
22472266
uint8_t type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
22482267

2268+
ZEND_ASSERT(!zend_isnan(dval));
2269+
22492270
if (type == IS_LONG) {
22502271
return ZEND_THREEWAY_COMPARE(dval, (double) str_lval);
22512272
}
@@ -2264,7 +2285,7 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
22642285

22652286
ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */
22662287
{
2267-
int converted = 0;
2288+
bool converted = false;
22682289
zval op1_copy, op2_copy;
22692290

22702291
while (1) {
@@ -2371,6 +2392,13 @@ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */
23712392
}
23722393

23732394
if (!converted) {
2395+
/* Handle NAN */
2396+
if (
2397+
Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1))
2398+
|| Z_TYPE_P(op2) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op2))
2399+
) {
2400+
return 1;
2401+
}
23742402
if (Z_TYPE_P(op1) < IS_TRUE) {
23752403
return zval_is_true(op2) ? -1 : 0;
23762404
} else if (Z_TYPE_P(op1) == IS_TRUE) {
@@ -2385,7 +2413,7 @@ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */
23852413
if (EG(exception)) {
23862414
return 1; /* to stop comparison of arrays */
23872415
}
2388-
converted = 1;
2416+
converted = true;
23892417
}
23902418
} else if (Z_TYPE_P(op1)==IS_ARRAY) {
23912419
return 1;
@@ -3543,6 +3571,9 @@ ZEND_API zend_string* ZEND_FASTCALL zend_double_to_str(double num)
35433571
int precision = (int) EG(precision);
35443572
zend_gcvt(num, precision ? precision : 1, '.', 'E', buf);
35453573
zend_string *str = zend_string_init(buf, strlen(buf), 0);
3574+
if (UNEXPECTED(zend_string_equals_literal(str, "NAN"))) {
3575+
zend_nan_coerced_to_type_warning(IS_STRING);
3576+
}
35463577
GC_ADD_FLAGS(str, IS_STR_VALID_UTF8);
35473578
return str;
35483579
}

0 commit comments

Comments
 (0)