Skip to content

Commit e504ab7

Browse files
committed
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 phpGH-20452.
1 parent 3e715d3 commit e504ab7

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ PHP NEWS
1111
. Fix crashes when trying to instantiate uninstantiable classes via date
1212
static constructors. (ndossche)
1313

14+
- DOM:
15+
. Fix memory leak when edge case is hit when registering xpath callback.
16+
(ndossche)
17+
1418
- Opcache:
1519
. Fixed bug GH-20329 (opcache.file_cache broken with full interned string
1620
buffer). (Arnaud)

ext/dom/tests/DOMXPath_callables_errors.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ try {
5757
echo $e->getMessage(), "\n";
5858
}
5959

60+
$x = new class {
61+
public static function dump() {}
62+
};
63+
64+
$classes = get_declared_classes();
65+
66+
try {
67+
$str = str_repeat($classes[count($classes) - 1] . '::dump', random_int(1, 1));
68+
$xpath->registerPhpFunctions([$str]);
69+
} catch (Throwable $e) {
70+
echo $e->getMessage(), "\n";
71+
}
72+
6073
?>
6174
--EXPECT--
6275
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
6780
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names
6881
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names
6982
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a valid callback name
83+
DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names

ext/dom/xpath_callbacks.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,16 @@ static zend_result php_dom_xpath_callback_ns_update_method_handler(
206206
ZVAL_PTR(&registered_value, fcc);
207207

208208
if (!key) {
209-
zend_string *str = zval_try_get_string(entry);
209+
zend_string *tmp_str;
210+
zend_string *str = zval_try_get_tmp_string(entry, &tmp_str);
210211
if (str && php_dom_xpath_is_callback_name_valid_and_throw(str, name_validation, true)) {
211212
zend_hash_update(&ns->functions, str, &registered_value);
212213
if (register_func) {
213214
register_func(ctxt, namespace, str);
214215
}
215-
zend_string_release_ex(str, false);
216+
zend_tmp_string_release(tmp_str);
216217
} else {
218+
zend_tmp_string_release(tmp_str);
217219
zend_fcc_dtor(fcc);
218220
efree(fcc);
219221
return FAILURE;

0 commit comments

Comments
 (0)