Skip to content

Commit 6ee6097

Browse files
committed
Constrain number parameter of numfmt_format to int|float
This is inline with similar changes to the math functions. Especially, array to number conversion makes no sense here, and is likely to hide a programming error. To make that feasible, we introduce the `n` specifier for classic ZPP so we can stick with `zend_parse_method_parameters()`. We also remove a test case, which has been degenerated to a ZPP test.
1 parent d9b80ef commit 6ee6097

9 files changed

+30
-40
lines changed

Zend/zend_API.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,16 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
522522
}
523523
break;
524524

525+
case 'n':
526+
{
527+
zval **p = va_arg(*va, zval **);
528+
529+
if (!zend_parse_arg_number(arg, p, check_null)) {
530+
return "number";
531+
}
532+
}
533+
break;
534+
525535
case 's':
526536
{
527537
char **p = va_arg(*va, char **);
@@ -793,7 +803,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
793803
case 'f': case 'A':
794804
case 'H': case 'p':
795805
case 'S': case 'P':
796-
case 'L':
806+
case 'L': case 'n':
797807
max_num_args++;
798808
break;
799809

Zend/zend_API.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e
13841384
#define Z_PARAM_LONG_OR_NULL(dest, is_null) \
13851385
Z_PARAM_LONG_EX(dest, is_null, 1, 0)
13861386

1387-
/* no old equivalent */
1387+
/* old "n" */
13881388
#define Z_PARAM_NUMBER_EX(dest, check_null) \
13891389
Z_PARAM_PROLOGUE(0, 0); \
13901390
if (UNEXPECTED(!zend_parse_arg_number(_arg, &dest, check_null))) { \

docs/parameter-parsing-api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ f - function or array containing php method call info (returned as
7575
h - array (returned as HashTable*)
7676
H - array or HASH_OF(object) (returned as HashTable*)
7777
l - long (zend_long)
78+
n - long or double (zval*)
7879
o - object of any type (zval*)
7980
O - object of specific type given by class entry (zval*, zend_class_entry)
8081
p - valid path (string without null bytes in the middle) and its length (char*, size_t)

ext/intl/formatter/formatter.stub.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public function __construct(string $locale, int $style, string $pattern = "") {}
88
public static function create(string $locale, int $style, string $pattern = "") {}
99

1010
/** @return string|false */
11-
public function format($value, int $type = NumberFormatter::TYPE_DEFAULT) {}
11+
public function format(int|float $value, int $type = NumberFormatter::TYPE_DEFAULT) {}
1212

1313
/** @return int|float|false */
1414
public function parse(string $value, int $type = NumberFormatter::TYPE_DOUBLE, &$position = null) {}
@@ -58,7 +58,7 @@ public function getErrorMessage() {}
5858

5959
function numfmt_create(string $locale, int $style, string $pattern = ""): ?NumberFormatter {}
6060

61-
function numfmt_format(NumberFormatter $fmt, $value, int $type = NumberFormatter::TYPE_DEFAULT): string|false {}
61+
function numfmt_format(NumberFormatter $fmt, int|float $value, int $type = NumberFormatter::TYPE_DEFAULT): string|false {}
6262

6363
function numfmt_parse(NumberFormatter $fmt, string $value, int $type = NumberFormatter::TYPE_DOUBLE, &$position = null): int|float|false {}
6464

ext/intl/formatter/formatter_arginfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ ZEND_END_ARG_INFO()
99
#define arginfo_class_NumberFormatter_create arginfo_class_NumberFormatter___construct
1010

1111
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter_format, 0, 0, 1)
12-
ZEND_ARG_INFO(0, value)
12+
ZEND_ARG_TYPE_MASK(0, value, MAY_BE_LONG|MAY_BE_DOUBLE)
1313
ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0)
1414
ZEND_END_ARG_INFO()
1515

@@ -73,7 +73,7 @@ ZEND_END_ARG_INFO()
7373

7474
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_numfmt_format, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
7575
ZEND_ARG_OBJ_INFO(0, fmt, NumberFormatter, 0)
76-
ZEND_ARG_INFO(0, value)
76+
ZEND_ARG_TYPE_MASK(0, value, MAY_BE_LONG|MAY_BE_DOUBLE)
7777
ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0)
7878
ZEND_END_ARG_INFO()
7979

ext/intl/formatter/formatter_format.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ PHP_FUNCTION( numfmt_format )
3939
FORMATTER_METHOD_INIT_VARS;
4040

4141
/* Parse parameters. */
42-
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oz|l",
42+
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "On|l",
4343
&object, NumberFormatter_ce_ptr, &number, &type ) == FAILURE )
4444
{
4545
RETURN_THROWS();
@@ -48,12 +48,6 @@ PHP_FUNCTION( numfmt_format )
4848
/* Fetch the object. */
4949
FORMATTER_METHOD_FETCH_OBJECT;
5050

51-
if(Z_TYPE_P(number) != IS_ARRAY) {
52-
convert_scalar_to_number_ex(number);
53-
} else {
54-
convert_to_long(number);
55-
}
56-
5751
if(type == FORMAT_TYPE_DEFAULT) {
5852
switch(Z_TYPE_P(number)) {
5953
case IS_LONG:

ext/intl/tests/bug48227.phpt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ Bug #48227 (NumberFormatter::format leaks memory)
66
<?php
77

88
$x = new NumberFormatter('en_US', NumberFormatter::DECIMAL);
9-
var_dump($x->format(''));
10-
var_dump($x->format(1));
11-
var_dump($x->format(NULL));
12-
var_dump($x->format($x));
9+
foreach (['', 1, NULL, $x] as $value) {
10+
try {
11+
var_dump($x->format($value));
12+
} catch (TypeError $ex) {
13+
echo $ex->getMessage(), PHP_EOL;
14+
}
15+
}
1316

1417
?>
15-
--EXPECTF--
16-
string(1) "0"
18+
--EXPECT--
19+
NumberFormatter::format() expects parameter 1 to be number, string given
1720
string(1) "1"
1821
string(1) "0"
19-
20-
Notice: Object of class NumberFormatter could not be converted to number in %s on line %d
21-
string(1) "1"
22+
NumberFormatter::format() expects parameter 1 to be number, object given

ext/intl/tests/bug53735.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ var_dump($f->format(0.26));
2525
--EXPECTF--
2626
string(%d) "5,50 kr%A"
2727
string(%d) "5,50 kr%A"
28+
29+
Notice: A non well formed numeric value encountered in %s on line %d
2830
string(%d) "5,00 kr%A"
2931
string(5) "23,25"
3032
string(3) "26%"

ext/intl/tests/bug79212.phpt

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)