Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Zend/zend_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ ZEND_API zend_result ZEND_FASTCALL zend_list_delete(zend_resource *res)
ZEND_API void ZEND_FASTCALL zend_list_free(zend_resource *res)
{
ZEND_ASSERT(GC_REFCOUNT(res) == 0);
zend_hash_index_del(&EG(regular_list), res->handle);
if (zend_hash_index_del(&EG(regular_list), res->handle) == FAILURE) {
efree_size(res, sizeof(zend_resource));
}
}

static void zend_resource_dtor(zend_resource *res)
Expand Down Expand Up @@ -177,7 +179,11 @@ void list_entry_destructor(zval *zv)

ZVAL_UNDEF(zv);
if (res->type >= 0) {
GC_ADDREF(res);
zend_resource_dtor(res);
if (GC_DELREF(res) != 0) {
return;
}
}
efree_size(res, sizeof(zend_resource));
}
Expand Down
32 changes: 32 additions & 0 deletions ext/standard/tests/filters/gh16321.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
GH-16321 (UAF when stream filter throws during stream close)
--FILE--
<?php
class TestFilter extends php_user_filter {
function filter($in, $out, &$consumed, $closing): int {
stream_bucket_new($this->stream, "42");
return PSFS_ERR_FATAL;
}
}

stream_filter_register("test_filter", "TestFilter");

function test() {
$stream = fopen('php://memory', 'wb+');
fwrite($stream, "data");
fseek($stream, 0, SEEK_SET);
stream_filter_append($stream, "test_filter");
stream_get_contents($stream);
}

test();
?>
--EXPECTF--
Warning: stream_get_contents(): Unprocessed filter buckets remaining on input brigade in %s on line %d

Fatal error: Uncaught TypeError: stream_bucket_new(): Argument #1 ($stream) must be an open stream resource in %s:%d
Stack trace:
#0 %s(%d): stream_bucket_new(Resource id #%d, '42')
#1 %s(%d): TestFilter->filter(Resource id #%d, Resource id #%d, 0, true)
#2 {main}
thrown in %s on line %d
Loading