Skip to content

Commit 85225a8

Browse files
Use zval_try_get_long() in NumberFormatter::format()
To improve precision handling in cases where the number doesn’t fit into a 32-bit or 64-bit integer. A float that doesn’t fit into a long will produce a deprecation warning; for NumberFormatter::TYPE_INT32, a number that doesn’t fit into 32 bits will additionally produce a ValueError. (This is inconsistent, but I’m not sure how to do it better.)
1 parent 1e7c64b commit 85225a8

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

ext/intl/formatter/formatter_format.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,37 @@ PHP_FUNCTION( numfmt_format )
5959

6060
switch(type) {
6161
case FORMAT_TYPE_INT32:
62+
{
63+
bool failed = true;
64+
int64_t value_64 = zval_try_get_long(number, &failed);
65+
if (failed || value_64 < -2147483648 || value_64 > 2147483647) {
66+
zend_argument_value_error(object ? 1 : 2, "must be numeric and fit in 32 bits");
67+
RETURN_THROWS();
68+
}
6269
convert_to_long(number);
63-
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number),
70+
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)value_64,
6471
formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
6572
if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
6673
intl_error_reset(INTL_DATA_ERROR_P(nfo));
6774
formatted = eumalloc(formatted_len);
68-
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number),
75+
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)value_64,
6976
formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
7077
if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
7178
efree(formatted);
7279
}
7380
}
7481
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
82+
}
7583
break;
7684

7785
case FORMAT_TYPE_INT64:
7886
{
79-
int64_t value = (Z_TYPE_P(number) == IS_DOUBLE)?(int64_t)Z_DVAL_P(number):Z_LVAL_P(number);
87+
bool failed = true;
88+
int64_t value = zval_try_get_long(number, &failed);
89+
if (failed) {
90+
zend_argument_value_error(object ? 1 : 2, "must be numeric");
91+
RETURN_THROWS();
92+
}
8093
formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
8194
if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
8295
intl_error_reset(INTL_DATA_ERROR_P(nfo));

0 commit comments

Comments
 (0)