Skip to content

Fix INF/NAN to string rendering #10298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Zend/zend_strtod.c
Original file line number Diff line number Diff line change
Expand Up @@ -3779,8 +3779,8 @@ ZEND_API char *zend_dtoa(double dd, int mode, int ndigits, int *decpt, bool *sig
#endif

u.d = dd;
if (word0(&u) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
if (!zend_isnan(dd) && word0(&u) & Sign_bit) {
/* set sign for everything, including 0's */
*sign = 1;
word0(&u) &= ~Sign_bit; /* clear sign bit */
}
Expand All @@ -3791,7 +3791,7 @@ ZEND_API char *zend_dtoa(double dd, int mode, int ndigits, int *decpt, bool *sig
#ifdef IEEE_Arith
if ((word0(&u) & Exp_mask) == Exp_mask)
#else
if (word0(&u) == 0x8000)
if (word0(&u) == 0x8000)
#endif
{
/* Infinity or NaN */
Expand Down
11 changes: 3 additions & 8 deletions ext/standard/formatted_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,17 +243,12 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos,
}

if (zend_isnan(number)) {
is_negative = (number<0);
php_sprintf_appendstring(buffer, pos, "NaN", 3, 0, padding,
alignment, 3, is_negative, 0, always_sign);
return;
always_sign = 0;
padding = ' ';
}

if (zend_isinf(number)) {
is_negative = (number<0);
php_sprintf_appendstring(buffer, pos, "INF", 3, 0, padding,
alignment, 3, is_negative, 0, always_sign);
return;
padding = ' ';
}

switch (fmt) {
Expand Down
2 changes: 1 addition & 1 deletion ext/standard/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *de
int count = 0;
int is_negative=0;

if (d < 0) {
if (d < 0 && !zend_isinf(d)) {
is_negative = 1;
d = -d;
}
Expand Down
40 changes: 20 additions & 20 deletions ext/standard/tests/bug49244.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ for ($i = 0; $i < 10; $i++) {

?>
--EXPECT--
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NaN} NaN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
{NAN} NAN
17 changes: 16 additions & 1 deletion ext/standard/tests/strings/number_format_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ $values = array(1234.5678,
"123.456789",
"12.3456789e1",
true,
false);
false,
INF,
-INF,
NAN);

echo "\n-- number_format tests.....default --\n";
for ($i = 0; $i < count($values); $i++) {
Expand Down Expand Up @@ -55,6 +58,9 @@ string(3) "123"
string(3) "123"
string(1) "1"
string(1) "0"
string(3) "inf"
string(4) "-inf"
string(3) "nan"

-- number_format tests.....with two dp --
string(8) "1,234.57"
Expand All @@ -68,6 +74,9 @@ string(6) "123.46"
string(6) "123.46"
string(4) "1.00"
string(4) "0.00"
string(3) "inf"
string(4) "-inf"
string(3) "nan"

-- number_format tests.....English format --
string(8) "1 234.57"
Expand All @@ -81,6 +90,9 @@ string(6) "123.46"
string(6) "123.46"
string(4) "1.00"
string(4) "0.00"
string(3) "inf"
string(4) "-inf"
string(3) "nan"

-- number_format tests.....French format --
string(8) "1 234,57"
Expand All @@ -94,3 +106,6 @@ string(6) "123,46"
string(6) "123,46"
string(4) "1,00"
string(4) "0,00"
string(3) "inf"
string(4) "-inf"
string(3) "nan"
123 changes: 123 additions & 0 deletions ext/standard/tests/strings/printf_inf_nan.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
--TEST--
Test printf INF/-INF/NAN rendering
--FILE--
<?php

$values = [
INF,
abs(log(0)),
-INF,
log(0),
NAN,
-NAN,
sqrt(-1)
];

$valuesShort = [
INF,
-INF,
NAN,
-NAN
];

// Test each float format
foreach ($values as $value) {
printf("#%1\$e# #%1\$E# #%1\$f# #%1\$F# #%1\$g# #%1\$G# #%1\$h# #%1\$H#\n", $value);
}

// Test padding and sign
vprintf(
"#%+f# #%+f# #%+f# #%+f#\n",
$valuesShort
);
vprintf(
"#%10f# #%10f# #%10f# #%10f#\n",
$valuesShort
);
vprintf(
"#%+10f# #%+10f# #%+10f# #%+10f#\n",
$valuesShort
);
vprintf(
"#%-10f# #%-10f# #%-10f# #%-10f#\n",
$valuesShort
);
vprintf(
"#%-+10f# #%-+10f# #%-+10f# #%-+10f#\n",
$valuesShort
);
vprintf(
"#%010f# #%010f# #%010f# #%010f#\n",
$valuesShort
);
vprintf(
"#%+010f# #%+010f# #%+010f# #%+010f#\n",
$valuesShort
);
vprintf(
"#%-010f# #%-010f# #%-010f# #%-010f#\n",
$valuesShort
);
vprintf(
"#%-+010f# #%-+010f# #%-+010f# #%-+010f#\n",
$valuesShort
);
vprintf(
"#%'n10f# #%'n10f# #%'n10f# #%'n10f#\n",
$valuesShort
);
vprintf(
"#%+'n10f# #%+'n10f# #%+'n10f# #%+'n10f#\n",
$valuesShort
);
vprintf(
"#%-'n10f# #%-'n10f# #%-'n10f# #%-'n10f#\n",
$valuesShort
);
vprintf(
"#%-+'n10f# #%-+'n10f# #%-+'n10f# #%-+'n10f#\n",
$valuesShort
);
vprintf(
"#% 10f# #% 10f# #% 10f# #% 10f#\n",
$valuesShort
);
vprintf(
"#%+ 10f# #%+ 10f# #%+ 10f# #%+ 10f#\n",
$valuesShort
);
vprintf(
"#%- 10f# #%- 10f# #%- 10f# #%- 10f#\n",
$valuesShort
);
vprintf(
"#%-+ 10f# #%-+ 10f# #%-+ 10f# #%-+ 10f#\n",
$valuesShort
);

?>
--EXPECT--
#INF# #INF# #INF# #INF# #INF# #INF# #INF# #INF#
#INF# #INF# #INF# #INF# #INF# #INF# #INF# #INF#
#-INF# #-INF# #-INF# #-INF# #-INF# #-INF# #-INF# #-INF#
#-INF# #-INF# #-INF# #-INF# #-INF# #-INF# #-INF# #-INF#
#NAN# #NAN# #NAN# #NAN# #NAN# #NAN# #NAN# #NAN#
#NAN# #NAN# #NAN# #NAN# #NAN# #NAN# #NAN# #NAN#
#NAN# #NAN# #NAN# #NAN# #NAN# #NAN# #NAN# #NAN#
#+INF# #-INF# #NAN# #NAN#
# INF# # -INF# # NAN# # NAN#
# +INF# # -INF# # NAN# # NAN#
#INF # #-INF # #NAN # #NAN #
#+INF # #-INF # #NAN # #NAN #
# INF# # -INF# # NAN# # NAN#
# +INF# # -INF# # NAN# # NAN#
#INF # #-INF # #NAN # #NAN #
#+INF # #-INF # #NAN # #NAN #
# INF# # -INF# # NAN# # NAN#
# +INF# # -INF# # NAN# # NAN#
#INF # #-INF # #NAN # #NAN #
#+INF # #-INF # #NAN # #NAN #
# INF# # -INF# # NAN# # NAN#
# +INF# # -INF# # NAN# # NAN#
#INF # #-INF # #NAN # #NAN #
#+INF # #-INF # #NAN # #NAN #
10 changes: 7 additions & 3 deletions main/snprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ PHPAPI char * php_conv_fp(char format, double num,
if (isalpha((int)*p)) {
*len = strlen(p);
memcpy(buf, p, *len + 1);
*is_negative = false;
free(p_orig);
return (buf);
}
Expand Down Expand Up @@ -872,8 +871,13 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{
s = "NAN";
s_len = 3;
} else if (zend_isinf(fp_num)) {
s = "INF";
s_len = 3;
if (fp_num > 0) {
s = "INF";
s_len = 3;
} else {
s = "-INF";
s_len = 4;
}
} else {
#ifdef ZTS
localeconv_r(&lconv);
Expand Down
9 changes: 7 additions & 2 deletions main/spprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,13 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_
s = "nan";
s_len = 3;
} else if (zend_isinf(fp_num)) {
s = "inf";
s_len = 3;
if (fp_num > 0) {
s = "inf";
s_len = 3;
} else {
s = "-inf";
s_len = 4;
}
} else {
#ifdef ZTS
localeconv_r(&lconv);
Expand Down