summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-02-16 16:41:43 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-02-16 16:48:35 +0100
commit6ee6097688a8c64e0e0ba166d48b16a93bf107a2 (patch)
tree9157214fbb184a14da756c195897ccf40e441d85
parentd9b80efb57ad46a5ba80581d823957471bfe4db0 (diff)
downloadphp-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.c12
-rw-r--r--Zend/zend_API.h2
-rw-r--r--docs/parameter-parsing-api.md1
-rw-r--r--ext/intl/formatter/formatter.stub.php4
-rw-r--r--ext/intl/formatter/formatter_arginfo.h4
-rw-r--r--ext/intl/formatter/formatter_format.c8
-rw-r--r--ext/intl/tests/bug48227.phpt19
-rw-r--r--ext/intl/tests/bug53735.phpt2
-rw-r--r--ext/intl/tests/bug79212.phpt18
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"