Skip to content

Add test for filter_var_array() leak when a nested element throws - #25365

Open
eyupcanakman wants to merge 1 commit into
php:PHP-8.5from
eyupcanakman:filter-var-array-throw-leak
Open

eyupcanakman wants to merge 1 commit into
php:PHP-8.5from
eyupcanakman:filter-var-array-throw-leak

Conversation

@eyupcanakman

@eyupcanakman eyupcanakman commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

The filter.c line this PR added came into PHP-8.5 with the merge of GH-25349, so the rebase leaves only the test.
It covers the two cases that leaked, a nested array failing under FILTER_THROW_ON_FAILURE and a callback that throws on a nested element.

filter
--FILE--
<?php
function leakcheck(callable $fn): bool {

@devnexen devnexen Nov 11, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be possible to simplify a tad

--- a/ext/filter/tests/filter_var_array_exception_leak.phpt
+++ b/ext/filter/tests/filter_var_array_exception_leak.phpt
@@ -4,34 +4,23 @@
 filter
 --FILE--
 <?php
-function leakcheck(callable $fn): bool {
-    $fn();
-    $before = memory_get_usage();
-    for ($i = 0; $i < 2000; $i++) {
-        $fn();
-    }
-    return memory_get_usage() - $before === 0;
+try {
+    filter_var_array(['a' => ['1', 'x']], ['a' => ['filter' => FILTER_VALIDATE_INT, 'flags' => FILTER_REQUIRE_ARRAY | FILTER_THROW_ON_FAILURE]]);
+} catch (Filter\FilterFailedException $e) {
+    echo $e::class, ': ', $e->getMessage(), PHP_EOL;
 }

-var_dump(leakcheck(function () {
-    try {
-        filter_var_array(['a' => ['1', 'x']], ['a' => ['filter' => FILTER_VALIDATE_INT, 'flags' => FILTER_REQUIRE_ARRAY | FILTER_THROW_ON_FAILURE]]);
-    } catch (Filter\FilterFailedException $e) {
-    }
-}));
-
-var_dump(leakcheck(function () {
-    try {
-        filter_var_array(['a' => ['1', 'x']], ['a' => ['filter' => FILTER_CALLBACK, 'options' => function ($value) {
-            if ($value === 'x') {
-                throw new Exception('callback failed');
-            }
-            return $value;
-        }]]);
-    } catch (Exception $e) {
-    }
-}));
+try {
+    filter_var_array(['a' => ['1', 'x']], ['a' => ['filter' => FILTER_CALLBACK, 'options' => function ($value) {
+        if ($value === 'x') {
+            throw new Exception('callback failed');
+        }
+        return $value;
+    }]]);
+} catch (Exception $e) {
+    echo $e::class, ': ', $e->getMessage(), PHP_EOL;
+}
 ?>
 --EXPECT--
-bool(true)
-bool(true)
+Filter\FilterFailedException: filter validation failed: filter int not satisfied by 'x'
+Exception: callback failed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, used your version. This is test-only now, the description says why.

phpGH-25349's merge into PHP-8.5 fixed the leak by freeing the copy before the return.
Covers the FILTER_THROW_ON_FAILURE and throwing callback cases.
@eyupcanakman
eyupcanakman force-pushed the filter-var-array-throw-leak branch from 66bfa65 to d28bd34 Compare November 12, 2026 17:52
@eyupcanakman eyupcanakman changed the title Fix memory leak in filter_var_array() when a nested element throws Add test for filter_var_array() leak when a nested element throws Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants