1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix memory leak when edge case is hit when registering xpath callback

This can happen if you have a valid callable name with a NUL byte in it,
on a non-interned string entry. This can be done by abusing anonymous
classes.

Closes GH-20452.
This commit is contained in:
Niels Dossche
2025-11-11 12:20:52 +01:00
parent 3e715d3361
commit e504ab778c
3 changed files with 22 additions and 2 deletions

4
NEWS
View File

@@ -11,6 +11,10 @@ PHP NEWS
. Fix crashes when trying to instantiate uninstantiable classes via date . Fix crashes when trying to instantiate uninstantiable classes via date
static constructors. (ndossche) static constructors. (ndossche)
- DOM:
. Fix memory leak when edge case is hit when registering xpath callback.
(ndossche)
- Opcache: - Opcache:
. Fixed bug GH-20329 (opcache.file_cache broken with full interned string . Fixed bug GH-20329 (opcache.file_cache broken with full interned string
buffer). (Arnaud) buffer). (Arnaud)

View File

@@ -57,6 +57,19 @@ try {
echo $e->getMessage(), "\n"; echo $e->getMessage(), "\n";
} }
$x = new class {
public static function dump() {}
};
$classes = get_declared_classes();
try {
$str = str_repeat($classes[count($classes) - 1] . '::dump', random_int(1, 1));
$xpath->registerPhpFunctions([$str]);
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
?> ?>
--EXPECT-- --EXPECT--
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a callable, function "nonexistent" not found or invalid function name DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a callable, function "nonexistent" not found or invalid function name
@@ -67,3 +80,4 @@ DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array with
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a valid callback name DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a valid callback name
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names

View File

@@ -206,14 +206,16 @@ static zend_result php_dom_xpath_callback_ns_update_method_handler(
ZVAL_PTR(&registered_value, fcc); ZVAL_PTR(&registered_value, fcc);
if (!key) { if (!key) {
zend_string *str = zval_try_get_string(entry); zend_string *tmp_str;
zend_string *str = zval_try_get_tmp_string(entry, &tmp_str);
if (str && php_dom_xpath_is_callback_name_valid_and_throw(str, name_validation, true)) { if (str && php_dom_xpath_is_callback_name_valid_and_throw(str, name_validation, true)) {
zend_hash_update(&ns->functions, str, &registered_value); zend_hash_update(&ns->functions, str, &registered_value);
if (register_func) { if (register_func) {
register_func(ctxt, namespace, str); register_func(ctxt, namespace, str);
} }
zend_string_release_ex(str, false); zend_tmp_string_release(tmp_str);
} else { } else {
zend_tmp_string_release(tmp_str);
zend_fcc_dtor(fcc); zend_fcc_dtor(fcc);
efree(fcc); efree(fcc);
return FAILURE; return FAILURE;