diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 6de7d255e067..e132c8b441f4 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -1339,7 +1339,12 @@ static void apply_filter_to_stream(bool append, INTERNAL_FUNCTION_PARAMETERS) } if (read_write & PHP_STREAM_FILTER_WRITE) { + bool originally_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream)); + if (!originally_no_fclose) { + stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE; + } if (filter == NULL) { RETURN_FALSE; } diff --git a/ext/standard/tests/streams/write_seek_mode-close-uaf.phpt b/ext/standard/tests/streams/write_seek_mode-close-uaf.phpt new file mode 100644 index 000000000000..7000eaad2c97 --- /dev/null +++ b/ext/standard/tests/streams/write_seek_mode-close-uaf.phpt @@ -0,0 +1,33 @@ +--TEST-- +`write_seek_mode` with a stringable object closing the stream triggers UAF +--EXTENSIONS-- +zlib +--CREDITS-- +Calif.io +--FILE-- + new CloseStreamForWriteSeekMode()], +); + +var_dump(is_resource($filter), is_resource($stream)); +?> +--EXPECTF-- +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d +bool(true) +bool(true) diff --git a/ext/standard/tests/streams/write_seek_mode-reuse.phpt b/ext/standard/tests/streams/write_seek_mode-reuse.phpt new file mode 100644 index 000000000000..72bb4cdb46f6 --- /dev/null +++ b/ext/standard/tests/streams/write_seek_mode-reuse.phpt @@ -0,0 +1,43 @@ +--TEST-- +`write_seek_mode` with a stringable object closing and reopening the stream triggers reuse +--EXTENSIONS-- +zlib +--CREDITS-- +Calif.io +--FILE-- + new ReplaceStreamForWriteSeekMode()], +); + +var_dump(is_resource($filter), is_resource($replacementStream)); +fwrite($replacementStream, str_repeat('A', 64)); +var_dump(stream_filter_remove($filter)); +rewind($replacementStream); +$raw = stream_get_contents($replacementStream); +var_dump(strlen($raw), bin2hex($raw)); +?> +--EXPECTF-- +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d +bool(true) +bool(true) +bool(true) +int(64) +string(128) "41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141"