Skip to content

Commit

Permalink
Fix GH-17037: UAF in user filter when adding existing filter name due…
Browse files Browse the repository at this point in the history
… to incorrect error handling

There are two functions that can each fail in their own way. If the last
function fails we have to remove the filter entry from the hash table,
otherwise we risk a UAF. Note also that removing the entry from the
table on failure will also free its memory.

Closes GH-17038.
  • Loading branch information
nielsdos committed Dec 4, 2024
1 parent 9c40bda commit 00f4881
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 4 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.3.16

- Streams:
. Fixed bug GH-17037 (UAF in user filter when adding existing filter name due
to incorrect error handling). (nielsdos)

19 Dec 2024, PHP 8.3.15

Expand Down
8 changes: 8 additions & 0 deletions ext/standard/tests/filters/gh17037.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--TEST--
GH-17037 (UAF in user filter when adding existing filter name due to incorrect error handling)
--FILE--
<?php
var_dump(stream_filter_register('string.toupper', 'filter_string_toupper'));
?>
--EXPECT--
bool(false)
12 changes: 8 additions & 4 deletions ext/standard/user_filters.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,13 +516,17 @@ PHP_FUNCTION(stream_filter_register)
fdat = ecalloc(1, sizeof(struct php_user_filter_data));
fdat->classname = zend_string_copy(classname);

if (zend_hash_add_ptr(BG(user_filter_map), filtername, fdat) != NULL &&
php_stream_filter_register_factory_volatile(filtername, &user_filter_factory) == SUCCESS) {
RETVAL_TRUE;
if (zend_hash_add_ptr(BG(user_filter_map), filtername, fdat) != NULL) {
if (php_stream_filter_register_factory_volatile(filtername, &user_filter_factory) == SUCCESS) {
RETURN_TRUE;
}

zend_hash_del(BG(user_filter_map), filtername);
} else {
zend_string_release_ex(classname, 0);
efree(fdat);
RETVAL_FALSE;
}

RETURN_FALSE;
}
/* }}} */

0 comments on commit 00f4881

Please sign in to comment.