Skip to content

Fix GH-17345: Bug #35916 was not completely fixed #18973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: PHP-8.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions ext/standard/tests/filters/gh17345.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
--TEST--
GH-17345 (Bug #35916 was not completely fixed)
--FILE--
<?php
$file = __DIR__ . "/gh17345.txt";
@unlink($file);

class strtoupper_filter extends php_user_filter
{
function filter($in, $out, &$consumed, $closing): int
{
while ($bucket=stream_bucket_make_writeable($in)) {
$bucket->data = strtoupper($bucket->data);
$consumed += $bucket->datalen;
stream_bucket_prepend($out, $bucket);
// Interleave new bucket
stream_bucket_prepend($out, clone $bucket);
stream_bucket_prepend($out, $bucket);
}
return PSFS_PASS_ON;
}

function onCreate(): bool
{
echo "fffffffffff\n";
return true;
}

function onClose(): void
{
echo "hello\n";
}
}

stream_filter_register("strtoupper", "strtoupper_filter");
$fp=fopen($file, "w");
stream_filter_append($fp, "strtoupper");
fread($fp, 1024);
fwrite($fp, "Thank you\n");
fclose($fp);
readfile($file);
unlink($file);
?>
--EXPECTF--
fffffffffff

Notice: fread(): Read of 8192 bytes failed with errno=9 Bad file descriptor in %s on line %d
hello
THANK YOU
14 changes: 8 additions & 6 deletions ext/standard/user_filters.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,17 +404,19 @@ static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS)
memcpy(bucket->buf, Z_STRVAL_P(pzdata), bucket->buflen);
}

/* If the bucket is already on a brigade we have to unlink it first to keep the
* linked list consistent. Furthermore, we can transfer the refcount in that case. */
if (bucket->brigade) {
php_stream_bucket_unlink(bucket);
} else {
bucket->refcount++;
}

if (append) {
php_stream_bucket_append(brigade, bucket);
} else {
php_stream_bucket_prepend(brigade, bucket);
}
/* This is a hack necessary to accommodate situations where bucket is appended to the stream
* multiple times. See bug35916.phpt for reference.
*/
if (bucket->refcount == 1) {
bucket->refcount++;
}
}
/* }}} */

Expand Down
1 change: 1 addition & 0 deletions main/streams/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_st

PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket)
{
/* TODO: this was added as a bad workaround for bug #35916 and should be removed in the future. */
if (brigade->tail == bucket) {
return;
}
Expand Down
Loading