diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2020-02-16 16:41:43 +0100 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2020-02-16 16:48:35 +0100 |
commit | 6ee6097688a8c64e0e0ba166d48b16a93bf107a2 (patch) | |
tree | 9157214fbb184a14da756c195897ccf40e441d85 | |
parent | d9b80efb57ad46a5ba80581d823957471bfe4db0 (diff) | |
download | php-git-6ee6097688a8c64e0e0ba166d48b16a93bf107a2.tar.gz |
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.
-rw-r--r-- | Zend/zend_API.c | 12 | ||||
-rw-r--r-- | Zend/zend_API.h | 2 | ||||
-rw-r--r-- | docs/parameter-parsing-api.md | 1 | ||||
-rw-r--r-- | ext/intl/formatter/formatter.stub.php | 4 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_arginfo.h | 4 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_format.c | 8 | ||||
-rw-r--r-- | ext/intl/tests/bug48227.phpt | 19 | ||||
-rw-r--r-- | ext/intl/tests/bug53735.phpt | 2 | ||||
-rw-r--r-- | ext/intl/tests/bug79212.phpt | 18 |
9 files changed, 30 insertions, 40 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index a3e452bf7d..ed8440f104 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -522,6 +522,16 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons } break; + case 'n': + { + zval **p = va_arg(*va, zval **); + + if (!zend_parse_arg_number(arg, p, check_null)) { + return "number"; + } + } + break; + case 's': { 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, case 'f': case 'A': case 'H': case 'p': case 'S': case 'P': - case 'L': + case 'L': case 'n': max_num_args++; break; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 70879fe2a8..2f1b58eb75 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1384,7 +1384,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e #define Z_PARAM_LONG_OR_NULL(dest, is_null) \ Z_PARAM_LONG_EX(dest, is_null, 1, 0) -/* no old equivalent */ +/* old "n" */ #define Z_PARAM_NUMBER_EX(dest, check_null) \ Z_PARAM_PROLOGUE(0, 0); \ if (UNEXPECTED(!zend_parse_arg_number(_arg, &dest, check_null))) { \ diff --git a/docs/parameter-parsing-api.md b/docs/parameter-parsing-api.md index e038a20dee..6bf035673b 100644 --- a/docs/parameter-parsing-api.md +++ b/docs/parameter-parsing-api.md @@ -75,6 +75,7 @@ f - function or array containing php method call info (returned as h - array (returned as HashTable*) H - array or HASH_OF(object) (returned as HashTable*) l - long (zend_long) +n - long or double (zval*) o - object of any type (zval*) O - object of specific type given by class entry (zval*, zend_class_entry) p - valid path (string without null bytes in the middle) and its length (char*, size_t) diff --git a/ext/intl/formatter/formatter.stub.php b/ext/intl/formatter/formatter.stub.php index 8d976f79e2..2edc28d6fd 100644 --- a/ext/intl/formatter/formatter.stub.php +++ b/ext/intl/formatter/formatter.stub.php @@ -8,7 +8,7 @@ class NumberFormatter public static function create(string $locale, int $style, string $pattern = "") {} /** @return string|false */ - public function format($value, int $type = NumberFormatter::TYPE_DEFAULT) {} + public function format(int|float $value, int $type = NumberFormatter::TYPE_DEFAULT) {} /** @return int|float|false */ public function parse(string $value, int $type = NumberFormatter::TYPE_DOUBLE, &$position = null) {} @@ -58,7 +58,7 @@ class NumberFormatter function numfmt_create(string $locale, int $style, string $pattern = ""): ?NumberFormatter {} -function numfmt_format(NumberFormatter $fmt, $value, int $type = NumberFormatter::TYPE_DEFAULT): string|false {} +function numfmt_format(NumberFormatter $fmt, int|float $value, int $type = NumberFormatter::TYPE_DEFAULT): string|false {} function numfmt_parse(NumberFormatter $fmt, string $value, int $type = NumberFormatter::TYPE_DOUBLE, &$position = null): int|float|false {} diff --git a/ext/intl/formatter/formatter_arginfo.h b/ext/intl/formatter/formatter_arginfo.h index 313d0dd714..eced76d82b 100644 --- a/ext/intl/formatter/formatter_arginfo.h +++ b/ext/intl/formatter/formatter_arginfo.h @@ -9,7 +9,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_NumberFormatter_create arginfo_class_NumberFormatter___construct ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter_format, 0, 0, 1) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_MASK(0, value, MAY_BE_LONG|MAY_BE_DOUBLE) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -73,7 +73,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_numfmt_format, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, fmt, NumberFormatter, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_MASK(0, value, MAY_BE_LONG|MAY_BE_DOUBLE) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_END_ARG_INFO() diff --git a/ext/intl/formatter/formatter_format.c b/ext/intl/formatter/formatter_format.c index 8c6a567eb2..4f87a981f2 100644 --- a/ext/intl/formatter/formatter_format.c +++ b/ext/intl/formatter/formatter_format.c @@ -39,7 +39,7 @@ PHP_FUNCTION( numfmt_format ) FORMATTER_METHOD_INIT_VARS; /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oz|l", + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "On|l", &object, NumberFormatter_ce_ptr, &number, &type ) == FAILURE ) { RETURN_THROWS(); @@ -48,12 +48,6 @@ PHP_FUNCTION( numfmt_format ) /* Fetch the object. */ FORMATTER_METHOD_FETCH_OBJECT; - if(Z_TYPE_P(number) != IS_ARRAY) { - convert_scalar_to_number_ex(number); - } else { - convert_to_long(number); - } - if(type == FORMAT_TYPE_DEFAULT) { switch(Z_TYPE_P(number)) { case IS_LONG: diff --git a/ext/intl/tests/bug48227.phpt b/ext/intl/tests/bug48227.phpt index 42a4ffaf86..a5946e035f 100644 --- a/ext/intl/tests/bug48227.phpt +++ b/ext/intl/tests/bug48227.phpt @@ -6,16 +6,17 @@ Bug #48227 (NumberFormatter::format leaks memory) <?php $x = new NumberFormatter('en_US', NumberFormatter::DECIMAL); -var_dump($x->format('')); -var_dump($x->format(1)); -var_dump($x->format(NULL)); -var_dump($x->format($x)); +foreach (['', 1, NULL, $x] as $value) { + try { + var_dump($x->format($value)); + } catch (TypeError $ex) { + echo $ex->getMessage(), PHP_EOL; + } +} ?> ---EXPECTF-- -string(1) "0" +--EXPECT-- +NumberFormatter::format() expects parameter 1 to be number, string given string(1) "1" string(1) "0" - -Notice: Object of class NumberFormatter could not be converted to number in %s on line %d -string(1) "1" +NumberFormatter::format() expects parameter 1 to be number, object given diff --git a/ext/intl/tests/bug53735.phpt b/ext/intl/tests/bug53735.phpt index 1deebb2276..66370e61f2 100644 --- a/ext/intl/tests/bug53735.phpt +++ b/ext/intl/tests/bug53735.phpt @@ -25,6 +25,8 @@ var_dump($f->format(0.26)); --EXPECTF-- string(%d) "5,50 kr%A" string(%d) "5,50 kr%A" + +Notice: A non well formed numeric value encountered in %s on line %d string(%d) "5,00 kr%A" string(5) "23,25" string(3) "26%" diff --git a/ext/intl/tests/bug79212.phpt b/ext/intl/tests/bug79212.phpt deleted file mode 100644 index 3d2083013b..0000000000 --- a/ext/intl/tests/bug79212.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Bug #79212 (NumberFormatter::format() may detect wrong type) ---SKIPIF-- -<?php -if (!extension_loaded('intl')) die('skip intl extension not available'); -if (!extension_loaded('gmp')) die('skip gmp extension not available'); -?> ---FILE-- -<?php -$fmt = new NumberFormatter('en_US', NumberFormatter::PATTERN_DECIMAL); -var_dump($fmt->format(gmp_init('823749273428379492374'))); - -$fmt = new NumberFormatter('en_US', NumberFormatter::PATTERN_DECIMAL); -var_dump($fmt->format([1], NumberFormatter::TYPE_INT64)); -?> ---EXPECTF-- -string(21) "823749273428379%c%c%c%c%c%c" -string(1) "1" |