diff --git a/ext/standard/tests/filters/gh17345.phpt b/ext/standard/tests/filters/gh17345.phpt new file mode 100644 index 0000000000000..f64659390a14f --- /dev/null +++ b/ext/standard/tests/filters/gh17345.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-17345 (Bug #35916 was not completely fixed) +--FILE-- +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 diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index acef5146fa25e..962eaaba7d6b0 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -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++; - } } /* }}} */ diff --git a/main/streams/filter.c b/main/streams/filter.c index abfc5c26ae12d..f6e47405dedec 100644 --- a/main/streams/filter.c +++ b/main/streams/filter.c @@ -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; }