From aed1e358dc8e1727bb996703b09c5f6d25e9719d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 11 Mar 2018 13:04:44 +0100 Subject: [PATCH] Implement #51368: php_filter_float does not allow custom thousand separators 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 | 5 +++++ ext/filter/logical_filters.c | 20 ++++++++++++++++++-- ext/filter/tests/bug51368.phpt | 24 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 ext/filter/tests/bug51368.phpt diff --git a/UPGRADING b/UPGRADING index be96e7bada..44bcae469c 100644 --- 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 diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index bc61107a6f..4dec0bba14 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -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 index 0000000000..7ecb720a1e --- /dev/null +++ b/ext/filter/tests/bug51368.phpt @@ -0,0 +1,24 @@ +--TEST-- +FR #51368 (php_filter_float does not allow custom thousand separators) +--SKIPIF-- + +--FILE-- + 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=== -- 2.40.0