diff --git a/ext/standard/math.c b/ext/standard/math.c index 221858e0c5cf7..801e8f6083661 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -282,15 +282,11 @@ PHP_FUNCTION(round) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() >= 2) { -#if SIZEOF_ZEND_LONG > SIZEOF_INT if (precision >= 0) { - places = precision > INT_MAX ? INT_MAX : (int)precision; + places = ZEND_LONG_INT_OVFL(precision) ? INT_MAX : (int)precision; } else { - places = precision <= INT_MIN ? INT_MIN+1 : (int)precision; + places = ZEND_LONG_INT_UDFL(precision) ? INT_MIN : (int)precision; } -#else - places = precision; -#endif } switch (Z_TYPE_P(value)) { @@ -1007,12 +1003,12 @@ PHP_FUNCTION(base_convert) /* }}} */ /* {{{ _php_math_number_format */ -PHPAPI zend_string *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep) +PHPAPI zend_string *_php_math_number_format(double d, zend_long dec, char dec_point, char thousand_sep) { return _php_math_number_format_ex(d, dec, &dec_point, 1, &thousand_sep, 1); } -PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *dec_point, +PHPAPI zend_string *_php_math_number_format_ex(double d, zend_long dec, const char *dec_point, size_t dec_point_len, const char *thousand_sep, size_t thousand_sep_len) { zend_string *res; @@ -1023,15 +1019,26 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *de size_t reslen = 0; int count = 0; int is_negative = 0; + int dec_round; + + // prevent integer overflow + if (dec >= 0) { + dec_round = ZEND_LONG_INT_OVFL(dec) ? INT_MAX : (int)dec; + } else { + dec_round = ZEND_LONG_INT_UDFL(dec) ? INT_MIN : (int)dec; + } if (d < 0) { is_negative = 1; d = -d; } - d = _php_math_round(d, dec, PHP_ROUND_HALF_UP); + d = _php_math_round(d, dec_round, PHP_ROUND_HALF_UP); dec = MAX(0, dec); - tmpbuf = strpprintf(0, "%.*F", dec, d); + dec_round = MAX(0, dec_round); + + tmpbuf = strpprintf(0, "%.*F", dec_round, d); + if (tmpbuf == NULL) { return NULL; } else if (!isdigit((int)ZSTR_VAL(tmpbuf)[0])) { @@ -1114,7 +1121,7 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *de * separator every three digits */ while (s >= ZSTR_VAL(tmpbuf)) { *t-- = *s--; - if (thousand_sep && (++count%3)==0 && s >= ZSTR_VAL(tmpbuf)) { + if (thousand_sep && (++count % 3) == 0 && s >= ZSTR_VAL(tmpbuf)) { t -= thousand_sep_len; memcpy(t + 1, thousand_sep, thousand_sep_len); } @@ -1279,7 +1286,7 @@ PHP_FUNCTION(number_format) break; case IS_DOUBLE: - RETURN_STR(_php_math_number_format_ex(Z_DVAL_P(num), (int)dec, dec_point, dec_point_len, thousand_sep, thousand_sep_len)); + RETURN_STR(_php_math_number_format_ex(Z_DVAL_P(num), dec, dec_point, dec_point_len, thousand_sep, thousand_sep_len)); break; EMPTY_SWITCH_DEFAULT_CASE() diff --git a/ext/standard/php_math.h b/ext/standard/php_math.h index 1cdba0fe9d0a6..f6073b3a88c75 100644 --- a/ext/standard/php_math.h +++ b/ext/standard/php_math.h @@ -19,8 +19,8 @@ #define PHP_MATH_H PHPAPI double _php_math_round(double value, int places, int mode); -PHPAPI zend_string *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep); -PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *dec_point, size_t dec_point_len, const char *thousand_sep, size_t thousand_sep_len); +PHPAPI zend_string *_php_math_number_format(double d, zend_long dec, char dec_point, char thousand_sep); +PHPAPI zend_string *_php_math_number_format_ex(double d, zend_long dec, const char *dec_point, size_t dec_point_len, const char *thousand_sep, size_t thousand_sep_len); PHPAPI zend_string *_php_math_number_format_long(zend_long num, zend_long dec, const char *dec_point, size_t dec_point_len, const char *thousand_sep, size_t thousand_sep_len); PHPAPI zend_string * _php_math_longtobase(zend_long arg, int base); PHPAPI zend_long _php_math_basetolong(zval *arg, int base); diff --git a/ext/standard/tests/math/number_format_basiclong_64bit.phpt b/ext/standard/tests/math/number_format_basiclong_64bit.phpt index 204fe420cd950..2f63091abb8c6 100644 --- a/ext/standard/tests/math/number_format_basiclong_64bit.phpt +++ b/ext/standard/tests/math/number_format_basiclong_64bit.phpt @@ -15,7 +15,7 @@ define("MIN_32Bit", -2147483647 - 1); $longVals = array( MAX_64Bit, MIN_64Bit, MAX_32Bit, MIN_32Bit, MAX_64Bit - MAX_32Bit, MIN_64Bit - MIN_32Bit, MAX_32Bit + 1, MIN_32Bit - 1, MAX_32Bit * 2, (MAX_32Bit * 2) + 1, (MAX_32Bit * 2) - 1, - MAX_64Bit -1, MIN_64Bit + 1 + MAX_64Bit -1, MAX_64Bit + 1, MIN_64Bit + 1, MIN_64Bit - 1 ); $precisions = array( @@ -41,7 +41,7 @@ foreach ($longVals as $longVal) { } ?> ---EXPECTF-- +--EXPECT-- --- testing: int(9223372036854775807) ... with precision 5: string(31) "9,223,372,036,854,775,807.00000" ... with precision 0: string(25) "9,223,372,036,854,775,807" @@ -52,7 +52,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(25) "9,200,000,000,000,000,000" ... with precision -19: string(26) "10,000,000,000,000,000,000" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(-9223372036854775808) ... with precision 5: string(32) "-9,223,372,036,854,775,808.00000" ... with precision 0: string(26) "-9,223,372,036,854,775,808" @@ -63,7 +63,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(26) "-9,200,000,000,000,000,000" ... with precision -19: string(27) "-10,000,000,000,000,000,000" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(2147483647) ... with precision 5: string(19) "2,147,483,647.00000" ... with precision 0: string(13) "2,147,483,647" @@ -74,7 +74,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(-2147483648) ... with precision 5: string(20) "-2,147,483,648.00000" ... with precision 0: string(14) "-2,147,483,648" @@ -85,7 +85,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(9223372034707292160) ... with precision 5: string(31) "9,223,372,034,707,292,160.00000" ... with precision 0: string(25) "9,223,372,034,707,292,160" @@ -96,7 +96,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(25) "9,200,000,000,000,000,000" ... with precision -19: string(26) "10,000,000,000,000,000,000" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(-9223372034707292160) ... with precision 5: string(32) "-9,223,372,034,707,292,160.00000" ... with precision 0: string(26) "-9,223,372,034,707,292,160" @@ -107,7 +107,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(26) "-9,200,000,000,000,000,000" ... with precision -19: string(27) "-10,000,000,000,000,000,000" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(2147483648) ... with precision 5: string(19) "2,147,483,648.00000" ... with precision 0: string(13) "2,147,483,648" @@ -118,7 +118,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(-2147483649) ... with precision 5: string(20) "-2,147,483,649.00000" ... with precision 0: string(14) "-2,147,483,649" @@ -129,7 +129,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(4294967294) ... with precision 5: string(19) "4,294,967,294.00000" ... with precision 0: string(13) "4,294,967,294" @@ -140,7 +140,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(4294967295) ... with precision 5: string(19) "4,294,967,295.00000" ... with precision 0: string(13) "4,294,967,295" @@ -151,7 +151,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(4294967293) ... with precision 5: string(19) "4,294,967,293.00000" ... with precision 0: string(13) "4,294,967,293" @@ -162,7 +162,7 @@ foreach ($longVals as $longVal) { ... with precision -17: string(1) "0" ... with precision -19: string(1) "0" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(9223372036854775806) ... with precision 5: string(31) "9,223,372,036,854,775,806.00000" ... with precision 0: string(25) "9,223,372,036,854,775,806" @@ -173,7 +173,18 @@ foreach ($longVals as $longVal) { ... with precision -17: string(25) "9,200,000,000,000,000,000" ... with precision -19: string(26) "10,000,000,000,000,000,000" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" +--- testing: float(9.223372036854776E+18) +... with precision 5: string(31) "9,223,372,036,854,775,808.00000" +... with precision 0: string(25) "9,223,372,036,854,775,808" +... with precision -1: string(25) "9,223,372,036,854,775,808" +... with precision -5: string(25) "9,223,372,036,854,800,384" +... with precision -10: string(25) "9,223,372,040,000,000,000" +... with precision -11: string(25) "9,223,372,000,000,000,000" +... with precision -17: string(25) "9,200,000,000,000,000,000" +... with precision -19: string(26) "10,000,000,000,000,000,000" +... with precision -20: string(1) "0" +... with precision -9223372036854775808: string(1) "0" --- testing: int(-9223372036854775807) ... with precision 5: string(32) "-9,223,372,036,854,775,807.00000" ... with precision 0: string(26) "-9,223,372,036,854,775,807" @@ -184,4 +195,15 @@ foreach ($longVals as $longVal) { ... with precision -17: string(26) "-9,200,000,000,000,000,000" ... with precision -19: string(27) "-10,000,000,000,000,000,000" ... with precision -20: string(1) "0" -... with precision %i: string(1) "0" +... with precision -9223372036854775808: string(1) "0" +--- testing: float(-9.223372036854776E+18) +... with precision 5: string(32) "-9,223,372,036,854,775,808.00000" +... with precision 0: string(26) "-9,223,372,036,854,775,808" +... with precision -1: string(26) "-9,223,372,036,854,775,808" +... with precision -5: string(26) "-9,223,372,036,854,800,384" +... with precision -10: string(26) "-9,223,372,040,000,000,000" +... with precision -11: string(26) "-9,223,372,000,000,000,000" +... with precision -17: string(26) "-9,200,000,000,000,000,000" +... with precision -19: string(27) "-10,000,000,000,000,000,000" +... with precision -20: string(1) "0" +... with precision -9223372036854775808: string(1) "0" diff --git a/ext/standard/tests/math/number_format_decimals.phpt b/ext/standard/tests/math/number_format_decimals.phpt index 3baa6fb6280a1..5fa45fddce2cd 100644 --- a/ext/standard/tests/math/number_format_decimals.phpt +++ b/ext/standard/tests/math/number_format_decimals.phpt @@ -29,7 +29,7 @@ $values = array( MIN_INT32, ); -$decimals = array(0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5); +$decimals = array(0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, PHP_INT_MIN); foreach ($values as $value) { echo 'testing '; @@ -42,7 +42,7 @@ foreach ($values as $value) { } ?> ---EXPECT-- +--EXPECTF-- testing float(1.5151) ... with decimal places of 0: string(1) "2" ... with decimal places of 1: string(3) "1.5" @@ -55,6 +55,7 @@ testing float(1.5151) ... with decimal places of -3: string(1) "0" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(15.151) ... with decimal places of 0: string(2) "15" ... with decimal places of 1: string(4) "15.2" @@ -67,6 +68,7 @@ testing float(15.151) ... with decimal places of -3: string(1) "0" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(151.51) ... with decimal places of 0: string(3) "152" ... with decimal places of 1: string(5) "151.5" @@ -79,6 +81,7 @@ testing float(151.51) ... with decimal places of -3: string(1) "0" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(1515.1) ... with decimal places of 0: string(5) "1,515" ... with decimal places of 1: string(7) "1,515.1" @@ -91,6 +94,7 @@ testing float(1515.1) ... with decimal places of -3: string(5) "2,000" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing int(15151) ... with decimal places of 0: string(6) "15,151" ... with decimal places of 1: string(8) "15,151.0" @@ -103,6 +107,7 @@ testing int(15151) ... with decimal places of -3: string(6) "15,000" ... with decimal places of -4: string(6) "20,000" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(-1.5151) ... with decimal places of 0: string(2) "-2" ... with decimal places of 1: string(4) "-1.5" @@ -115,6 +120,7 @@ testing float(-1.5151) ... with decimal places of -3: string(1) "0" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(-15.151) ... with decimal places of 0: string(3) "-15" ... with decimal places of 1: string(5) "-15.2" @@ -127,6 +133,7 @@ testing float(-15.151) ... with decimal places of -3: string(1) "0" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(-151.51) ... with decimal places of 0: string(4) "-152" ... with decimal places of 1: string(6) "-151.5" @@ -139,6 +146,7 @@ testing float(-151.51) ... with decimal places of -3: string(1) "0" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(-1515.1) ... with decimal places of 0: string(6) "-1,515" ... with decimal places of 1: string(8) "-1,515.1" @@ -151,6 +159,7 @@ testing float(-1515.1) ... with decimal places of -3: string(6) "-2,000" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing int(-15151) ... with decimal places of 0: string(7) "-15,151" ... with decimal places of 1: string(9) "-15,151.0" @@ -163,6 +172,7 @@ testing int(-15151) ... with decimal places of -3: string(7) "-15,000" ... with decimal places of -4: string(7) "-20,000" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing int(999) ... with decimal places of 0: string(3) "999" ... with decimal places of 1: string(5) "999.0" @@ -175,6 +185,7 @@ testing int(999) ... with decimal places of -3: string(5) "1,000" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing int(-999) ... with decimal places of 0: string(4) "-999" ... with decimal places of 1: string(6) "-999.0" @@ -187,6 +198,7 @@ testing int(-999) ... with decimal places of -3: string(6) "-1,000" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(999) ... with decimal places of 0: string(3) "999" ... with decimal places of 1: string(5) "999.0" @@ -199,6 +211,7 @@ testing float(999) ... with decimal places of -3: string(5) "1,000" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing float(-999) ... with decimal places of 0: string(4) "-999" ... with decimal places of 1: string(6) "-999.0" @@ -211,6 +224,7 @@ testing float(-999) ... with decimal places of -3: string(6) "-1,000" ... with decimal places of -4: string(1) "0" ... with decimal places of -5: string(1) "0" +... with decimal places of %i: string(1) "0" testing int(999999) ... with decimal places of 0: string(7) "999,999" ... with decimal places of 1: string(9) "999,999.0" @@ -223,6 +237,7 @@ testing int(999999) ... with decimal places of -3: string(9) "1,000,000" ... with decimal places of -4: string(9) "1,000,000" ... with decimal places of -5: string(9) "1,000,000" +... with decimal places of %i: string(1) "0" testing int(-999999) ... with decimal places of 0: string(8) "-999,999" ... with decimal places of 1: string(10) "-999,999.0" @@ -235,6 +250,7 @@ testing int(-999999) ... with decimal places of -3: string(10) "-1,000,000" ... with decimal places of -4: string(10) "-1,000,000" ... with decimal places of -5: string(10) "-1,000,000" +... with decimal places of %i: string(1) "0" testing float(999999) ... with decimal places of 0: string(7) "999,999" ... with decimal places of 1: string(9) "999,999.0" @@ -247,6 +263,7 @@ testing float(999999) ... with decimal places of -3: string(9) "1,000,000" ... with decimal places of -4: string(9) "1,000,000" ... with decimal places of -5: string(9) "1,000,000" +... with decimal places of %i: string(1) "0" testing float(-999999) ... with decimal places of 0: string(8) "-999,999" ... with decimal places of 1: string(10) "-999,999.0" @@ -259,6 +276,7 @@ testing float(-999999) ... with decimal places of -3: string(10) "-1,000,000" ... with decimal places of -4: string(10) "-1,000,000" ... with decimal places of -5: string(10) "-1,000,000" +... with decimal places of %i: string(1) "0" testing int(2147483647) ... with decimal places of 0: string(13) "2,147,483,647" ... with decimal places of 1: string(15) "2,147,483,647.0" @@ -271,6 +289,7 @@ testing int(2147483647) ... with decimal places of -3: string(13) "2,147,484,000" ... with decimal places of -4: string(13) "2,147,480,000" ... with decimal places of -5: string(13) "2,147,500,000" +... with decimal places of %i: string(1) "0" testing int(-2147483648) ... with decimal places of 0: string(14) "-2,147,483,648" ... with decimal places of 1: string(16) "-2,147,483,648.0" @@ -283,3 +302,4 @@ testing int(-2147483648) ... with decimal places of -3: string(14) "-2,147,484,000" ... with decimal places of -4: string(14) "-2,147,480,000" ... with decimal places of -5: string(14) "-2,147,500,000" +... with decimal places of %i: string(1) "0"