diff --git a/ext/standard/tests/gh22818.phpt b/ext/standard/tests/gh22818.phpt new file mode 100644 index 000000000000..e6ebaeecce5d --- /dev/null +++ b/ext/standard/tests/gh22818.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug GH-22818: user_filter_factory_create assertion failure on shutdown re-registration +--FILE-- + +--EXPECTF-- +done + +Warning: stream_filter_append(): Unable to create or locate filter "rotator_notWorking" in %s on line %d diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index 986bbbd5f4d3..9d249ac3abfb 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -618,6 +618,13 @@ PHP_FUNCTION(stream_filter_register) RETURN_THROWS(); } + + /* Register the factory first; if that fails, don't (re)create the map, + * which would leak during shutdown re-registration. */ + if (php_stream_filter_register_factory_volatile(filtername, &user_filter_factory) == FAILURE) { + RETURN_FALSE; + } + if (!BG(user_filter_map)) { BG(user_filter_map) = (HashTable*) emalloc(sizeof(HashTable)); zend_hash_init(BG(user_filter_map), 8, NULL, (dtor_func_t) filter_item_dtor, 0); @@ -626,17 +633,8 @@ 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) { - 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); - } + zend_hash_add_ptr(BG(user_filter_map), filtername, fdat); - RETURN_FALSE; + RETURN_TRUE; } /* }}} */