Skip to content

Commit 7d9650e

Browse files
committed
1 parent e99d006 commit 7d9650e

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

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/zend_operators.c

Lines changed: 22 additions & 0 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:
@@ -3543,6 +3562,9 @@ ZEND_API zend_string* ZEND_FASTCALL zend_double_to_str(double num)
35433562
int precision = (int) EG(precision);
35443563
zend_gcvt(num, precision ? precision : 1, '.', 'E', buf);
35453564
zend_string *str = zend_string_init(buf, strlen(buf), 0);
3565+
if (UNEXPECTED(zend_string_equals_literal(str, "NAN"))) {
3566+
zend_nan_coerced_to_type_warning(IS_STRING);
3567+
}
35463568
GC_ADD_FLAGS(str, IS_STR_VALID_UTF8);
35473569
return str;
35483570
}

Zend/zend_operators.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,18 @@ ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const
115115
# define ZEND_DOUBLE_FITS_LONG(d) (!((d) >= (double)ZEND_LONG_MAX || (d) < (double)ZEND_LONG_MIN))
116116
#endif
117117

118+
ZEND_API void zend_incompatible_double_to_long_error(double d);
119+
ZEND_API void zend_incompatible_string_to_long_error(const zend_string *s);
120+
ZEND_API void ZEND_COLD zend_nan_coerced_to_type_warning(uint8_t type);
121+
118122
ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d);
119123

120124
static zend_always_inline zend_long zend_dval_to_lval(double d)
121125
{
122126
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
127+
if (zend_isnan(d)) {
128+
zend_nan_coerced_to_type_warning(IS_LONG);
129+
}
123130
return 0;
124131
} else if (!ZEND_DOUBLE_FITS_LONG(d)) {
125132
return zend_dval_to_lval_slow(d);
@@ -131,6 +138,9 @@ static zend_always_inline zend_long zend_dval_to_lval(double d)
131138
static zend_always_inline zend_long zend_dval_to_lval_cap(double d)
132139
{
133140
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
141+
if (zend_isnan(d)) {
142+
zend_nan_coerced_to_type_warning(IS_LONG);
143+
}
134144
return 0;
135145
} else if (!ZEND_DOUBLE_FITS_LONG(d)) {
136146
return (d > 0 ? ZEND_LONG_MAX : ZEND_LONG_MIN);
@@ -143,9 +153,6 @@ static zend_always_inline bool zend_is_long_compatible(double d, zend_long l) {
143153
return (double)l == d;
144154
}
145155

146-
ZEND_API void zend_incompatible_double_to_long_error(double d);
147-
ZEND_API void zend_incompatible_string_to_long_error(const zend_string *s);
148-
149156
static zend_always_inline zend_long zend_dval_to_lval_safe(double d)
150157
{
151158
zend_long l = zend_dval_to_lval(d);
@@ -405,6 +412,9 @@ static zend_always_inline bool i_zend_is_true(const zval *op)
405412
}
406413
break;
407414
case IS_DOUBLE:
415+
if (UNEXPECTED(zend_isnan(Z_DVAL_P(op)))) {
416+
zend_nan_coerced_to_type_warning(_IS_BOOL);
417+
}
408418
if (Z_DVAL_P(op)) {
409419
result = 1;
410420
}

0 commit comments

Comments
 (0)