[php-src] PR #23403: ext/filter: Narrow the return type of filter_var_array() to array|false

From: Date: Fri, 21 Aug 2026 14:10:22 +0000
Subject: [php-src] PR #23403: ext/filter: Narrow the return type of filter_var_array() to array|false
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38044@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23403 Author: lacatoire filter_var_array() declares array|false|null, but null is unreachable. The function has exactly two exits: RETURN_FALSE when the filter id is unknown, and php_filter_array_handler(), which establishes an array on both of its branches before doing anything else — ZVAL_DUP() of the input, which is a Z_PARAM_ARRAY, or array_init(). The handler's remaining exits are RETURN_THROWS(). The sibling filter_input_array() is declared identically and does return null, deliberately, since its source superglobal may not exist: ```c if (!array_input) { RETURN_NULL(); } ``` That case has no equivalent in filter_var_array(), whose source is a required array parameter. The two signatures look symmetrical but only one of them can produce null. ## Verification Swept every registered filter from filter_list(), as the global int form and inside an options array, across six flag combinations including FILTER_NULL_ON_FAILURE, FILTER_FORCE_ARRAY and FILTER_REQUIRE_SCALAR, against inputs chosen to make filters fail, with $add_empty both ways. 3024 calls on 8.5.4: array 2848 times, TypeError 88, ValueError 88, plus false for the unknown filter id. null never appears. Worth noting that null remains an ordinary **element** value in the returned array, which is likely where the wider union came from: ```php filter_var_array(['a' => 'x'], ['a' => ['filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE]]); ``` That is the value type, not the return type. Only the stub changes; the arginfo is regenerated and the edit is confined to arginfo_filter_var_array, filter_input_array keeps MAY_BE_NULL. ## Note This is behaviour-preserving on the engine side, but it does tighten what userland is told, and it shows up in ReflectionFunction::getReturnType(). Whether that belongs in a minor or should wait for a major is the maintainers' call.

« previous php.git-pulls (#38044) next »