]> granicus.if.org Git - php/commitdiff
Implement #51368: php_filter_float does not allow custom thousand separators
authorChristoph M. Becker <cmbecker69@gmx.de>
Sun, 11 Mar 2018 12:04:44 +0000 (13:04 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Sat, 24 Mar 2018 14:04:32 +0000 (15:04 +0100)
A set of hard-coded thousand separator characters (presently, `',.`) is
somewhat limited (users may prefer other separators, such as spaces or
underscores), as well as somewhat too liberal (arbitrary combinations
of different thousand separators are presently possible).  Therefore we
introduce a `thousand` option analogous to `decimal`, which allows to
define the desired thousand separators as non-empty string, defaulting
to `',.`.  While we easily could support empty strings here as well,
that would not make much sense, since this behavior can more easily be
accomplished by not setting the `FILTER_FLAG_ALLOW_THOUSAND` flag in
the first place.

UPGRADING
ext/filter/logical_filters.c
ext/filter/tests/bug51368.phpt [new file with mode: 0644]

index be96e7bada0982e41bb24497683c3ee8babd1de3..44bcae469cfa3d0fedc3f89b982613f24e8ead93 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -154,6 +154,11 @@ JSON:
  Curl:
   . libcurl >= 7.15.5 is now required.
 
+ Filter:
+  . FILTER_VALIDATE_FLOAT now also supports a `thousand` option, which
+    defines the set of allowed thousand separator chars.  The default (`"',."`)
+    is fully backward compatible with former PHP versions.
+
  FTP:
   . Set default transfer mode to binary
 
index bc61107a6f3dbc359d475cd1ff22a037b99e8cef..4dec0bba143a61404199754ecf01c5f0e1ffbc06 100644 (file)
@@ -330,7 +330,10 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
        int decimal_set;
        size_t decimal_len;
        char dec_sep = '.';
-       char tsd_sep[3] = "',.";
+       char *thousand;
+       int thousand_set;
+       size_t thousand_len;
+       char *tsd_sep;
 
        zend_long lval;
        double dval;
@@ -354,6 +357,19 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
                }
        }
 
+       FETCH_STRING_OPTION(thousand, "thousand");
+
+       if (thousand_set) {
+               if (thousand_len < 1) {
+                       php_error_docref(NULL, E_WARNING, "thousand separator must be at least one char");
+                       RETURN_VALIDATION_FAILED
+               } else {
+                       tsd_sep = thousand;
+               }
+       } else {
+               tsd_sep = "',.";
+       }
+
        num = p = emalloc(len+1);
        if (str < end && (*str == '+' || *str == '-')) {
                *p++ = *str++;
@@ -387,7 +403,7 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
                        }
                        break;
                }
-               if ((flags & FILTER_FLAG_ALLOW_THOUSAND) && (*str == tsd_sep[0] || *str == tsd_sep[1] || *str == tsd_sep[2])) {
+               if ((flags & FILTER_FLAG_ALLOW_THOUSAND) && strchr(tsd_sep, *str)) {
                        if (first?(n < 1 || n > 3):(n != 3)) {
                                goto error;
                        }
diff --git a/ext/filter/tests/bug51368.phpt b/ext/filter/tests/bug51368.phpt
new file mode 100644 (file)
index 0000000..7ecb720
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+FR #51368 (php_filter_float does not allow custom thousand separators)
+--SKIPIF--
+<?php
+if (!extension_loaded('filter')) die('skip filter extension not available');
+?>
+--FILE--
+<?php
+$options = ['flags' => FILTER_FLAG_ALLOW_THOUSAND, 'options' => ['thousand' => ' ']];
+var_dump(
+    filter_var('1 000', FILTER_VALIDATE_FLOAT, $options),
+    filter_var('1 234.567', FILTER_VALIDATE_FLOAT, $options)
+);
+$options = ['flags' => FILTER_FLAG_ALLOW_THOUSAND, 'options' => ['thousand' => '']];
+var_dump(filter_var('12345', FILTER_VALIDATE_FLOAT, $options));
+?>
+===DONE===
+--EXPECTF--
+float(1000)
+float(1234.567)
+
+Warning: filter_var(): thousand separator must be at least one char in %s on line %d
+bool(false)
+===DONE===