From c2fb10d2d20208a79031eb3760d1327defe7983a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 13 Sep 2023 19:01:53 +0200 Subject: [PATCH] Fix filter_var with callback and explicit REQUIRE_SCALAR For some reason, FILTER_CALLBACK disables the FILTER_REQUIRE_SCALAR flag that is normally set by default. While surprising, this is not something we can change. However, even specifying FILTER_REQUIRE_SCALAR explicitly does not corrently set this flag. This is because FILTER_CALLBACK zeroes the flags after they have been populated from the parameters. We reverse the checks to make explicitly specifying the flag behave as expected. Closes GH-12203 --- NEWS | 3 +++ ext/filter/filter.c | 16 ++++++++-------- .../tests/filter_callback_require_scalar.phpt | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 ext/filter/tests/filter_callback_require_scalar.phpt diff --git a/NEWS b/NEWS index c0eb2aedc74..921de39f35b 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,9 @@ PHP NEWS - DOM: . Fix memory leak when setting an invalid DOMDocument encoding. (nielsdos) +- Filter: + . Fix explicit FILTER_REQUIRE_SCALAR with FILTER_CALLBACK (ilutov) + - Iconv: . Fixed build for NetBSD which still uses the old iconv signature. (David Carlier) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 836ee8345af..edde05dcc99 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -551,14 +551,6 @@ static void php_filter_call( filter = zval_get_long(option); } - if ((option = zend_hash_str_find(filter_args_ht, "flags", sizeof("flags") - 1)) != NULL) { - filter_flags = zval_get_long(option); - - if (!(filter_flags & FILTER_REQUIRE_ARRAY || filter_flags & FILTER_FORCE_ARRAY)) { - filter_flags |= FILTER_REQUIRE_SCALAR; - } - } - if ((option = zend_hash_str_find_deref(filter_args_ht, "options", sizeof("options") - 1)) != NULL) { if (filter != FILTER_CALLBACK) { if (Z_TYPE_P(option) == IS_ARRAY) { @@ -569,6 +561,14 @@ static void php_filter_call( filter_flags = 0; } } + + if ((option = zend_hash_str_find(filter_args_ht, "flags", sizeof("flags") - 1)) != NULL) { + filter_flags = zval_get_long(option); + + if (!(filter_flags & FILTER_REQUIRE_ARRAY || filter_flags & FILTER_FORCE_ARRAY)) { + filter_flags |= FILTER_REQUIRE_SCALAR; + } + } } if (Z_TYPE_P(filtered) == IS_ARRAY) { diff --git a/ext/filter/tests/filter_callback_require_scalar.phpt b/ext/filter/tests/filter_callback_require_scalar.phpt new file mode 100644 index 00000000000..7259d1823d8 --- /dev/null +++ b/ext/filter/tests/filter_callback_require_scalar.phpt @@ -0,0 +1,18 @@ +--TEST-- +FILTER_CALLBACK with explicit FILTER_REQUIRE_SCALAR +--EXTENSIONS-- +filter +--FILE-- + $callback, 'flags' => FILTER_REQUIRE_SCALAR]); +} +var_dump(test('test')); +var_dump(test(['test'])); +?> +--EXPECT-- +string(4) "test" +bool(false)