Fix leaks from unprocessed user filter buckets - #23267
Conversation
|
Looks good to me. The same error message ("Unprocessed filter buckets remaining on input brigade") is present around line 190, if |
|
The drain is in the right function, but doing it unconditionally destroys data on the read path.
class defer extends php_user_filter {
private int $calls = 0;
public function filter($in, $out, &$consumed, bool $closing): int {
$this->calls++;
$buckets = [];
while ($b = stream_bucket_make_writeable($in)) { $buckets[] = $b; }
if ($this->calls < 3) {
foreach ($buckets as $b) { stream_bucket_prepend($in, $b); }
return PSFS_FEED_ME;
}
foreach ($buckets as $b) { stream_bucket_append($out, $b); }
return PSFS_PASS_ON;
}
}
stream_filter_register("defer", "defer");
$fp = fopen($threeChunkFile, 'r');
stream_filter_append($fp, "defer", STREAM_FILTER_READ);
var_dump(strlen(stream_get_contents($fp)));24576 on master, 8192 with this patch. The buckets are userland-owned after I do not think the deferral pattern is worth preserving as such, but silently truncating a stream is worse than the leak. Gating the drain on Two smaller things. The |
|
On the second warning site: the caller does not always clean up. On the branch: the leak is on 8.4 and 8.5 too, so the fix belongs on the lowest affected branch rather than master. The behavior question above is the reason to settle it on master first. Also worth linking up: #20058 does the same thing, has been open since October, and additionally drains |
A user filter can return without having processed every bucket in its input
brigade; the stream layer then drops the brigade, orphaning the remaining
buckets. Unlink and release leftover buckets when the filter finishes. This
resolves two XFAILs in ext/standard/tests/filters.