Skip to content

Commit 07df659

Browse files
berbeflonikic
authored andcommitted
Added range options to the float validation filter
php_filter_int (called via the constant FILTER_VALIDATE_INT) has the options min_range and max_range. they allow the user to not only test if a value is a double but also if the value is inside a specific range. php_filter_float (called via the constant FILTER_VALIDATE_FLOAT) didn't provide this yet, making validation of numeric but not-only-int values more complicated for the user. this commits implements the options min_range and max_range for the function php_filter_float to fix this inconsistency.
1 parent 897cb8b commit 07df659

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ PHP 7.4 UPGRADE NOTES
121121
. Support for WeakReferences has been added.
122122
RFC: https://wiki.php.net/rfc/weakrefs
123123

124+
- Filter:
125+
. The FILTER_VALIDATE_FLOAT filter now supports the min_range and max_range
126+
options, with the same semantics as FILTER_VALIDATE_INT.
127+
124128
- FFI:
125129
. A new extension which provides a simple way to call native functions, access
126130
native variables and create/access data structures defined in C libraries.

ext/filter/logical_filters.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@
3434
#endif
3535

3636

37+
/* {{{ FETCH_DOUBLE_OPTION(var_name, option_name) */
38+
#define FETCH_DOUBLE_OPTION(var_name, option_name) \
39+
var_name = 0; \
40+
var_name##_set = 0; \
41+
if (option_array) { \
42+
if ((option_val = zend_hash_str_find(Z_ARRVAL_P(option_array), option_name, sizeof(option_name) - 1)) != NULL) { \
43+
var_name = zval_get_double(option_val); \
44+
var_name##_set = 1; \
45+
} \
46+
}
47+
/* }}} */
48+
3749
/* {{{ FETCH_LONG_OPTION(var_name, option_name) */
3850
#define FETCH_LONG_OPTION(var_name, option_name) \
3951
var_name = 0; \
@@ -335,6 +347,8 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
335347

336348
zend_long lval;
337349
double dval;
350+
double min_range, max_range;
351+
int min_range_set, max_range_set;
338352

339353
int first, n;
340354

@@ -368,6 +382,9 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
368382
tsd_sep = "',.";
369383
}
370384

385+
FETCH_DOUBLE_OPTION(min_range, "min_range");
386+
FETCH_DOUBLE_OPTION(max_range, "max_range");
387+
371388
num = p = emalloc(len+1);
372389
if (str < end && (*str == '+' || *str == '-')) {
373390
*p++ = *str++;
@@ -419,12 +436,18 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
419436
switch (is_numeric_string(num, p - num, &lval, &dval, 0)) {
420437
case IS_LONG:
421438
zval_ptr_dtor(value);
439+
if ((min_range_set && (lval < min_range)) || (max_range_set && (lval > max_range))) {
440+
goto error;
441+
}
422442
ZVAL_DOUBLE(value, (double)lval);
423443
break;
424444
case IS_DOUBLE:
425445
if ((!dval && p - num > 1 && strpbrk(num, "123456789")) || !zend_finite(dval)) {
426446
goto error;
427447
}
448+
if ((min_range_set && (dval < min_range)) || (max_range_set && (dval > max_range))) {
449+
goto error;
450+
}
428451
zval_ptr_dtor(value);
429452
ZVAL_DOUBLE(value, dval);
430453
break;

ext/filter/tests/060.phpt

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
--TEST--
2+
filter_var() - tests for the range options of filter FILTER_VALIDATE_FLOAT
3+
--INI--
4+
precision=14
5+
--SKIPIF--
6+
<?php if (!extension_loaded("filter")) die("skip"); ?>
7+
--FILE--
8+
<?php
9+
10+
$values = [
11+
null,
12+
false,
13+
0,
14+
-1,
15+
'-5.4',
16+
'-5.5',
17+
'2,000.00',
18+
'2,000.01',
19+
'1,999.9999999'
20+
];
21+
22+
var_dump(filter_var(
23+
$values,
24+
FILTER_VALIDATE_FLOAT,
25+
[
26+
'options' => [
27+
'min_range' => -5.4,
28+
'max_range' => 2000,
29+
],
30+
'flags' => FILTER_FLAG_ALLOW_THOUSAND | FILTER_REQUIRE_ARRAY
31+
]
32+
));
33+
34+
var_dump(filter_var(
35+
'1000',
36+
FILTER_VALIDATE_FLOAT,
37+
[
38+
'options' => [
39+
'max_range' => 999.999,
40+
'default' => 0
41+
]
42+
]
43+
));
44+
45+
var_dump(filter_var(
46+
'-11',
47+
FILTER_VALIDATE_FLOAT,
48+
[
49+
'options' => [
50+
'min_range' => -10,
51+
'default' => 0
52+
]
53+
]
54+
));
55+
?>
56+
--EXPECT--
57+
array(9) {
58+
[0]=>
59+
bool(false)
60+
[1]=>
61+
bool(false)
62+
[2]=>
63+
float(0)
64+
[3]=>
65+
float(-1)
66+
[4]=>
67+
float(-5.4)
68+
[5]=>
69+
bool(false)
70+
[6]=>
71+
float(2000)
72+
[7]=>
73+
bool(false)
74+
[8]=>
75+
float(1999.9999999)
76+
}
77+
int(0)
78+
int(0)

0 commit comments

Comments
 (0)