Skip to content

Commit 6eb8d06

Browse files
committed
Fix GH-23897: php:function() assertion after failed registerPHPFunctions()
A registerPHPFunctions() call that threw on a non callable name had already allocated the callback namespace, leaving it in PHP_DOM_REG_FUNC_MODE_NONE. The next php:function() call dispatched into it and tripped the MODE_SET assertion. Close GH-23900
1 parent 342a746 commit 6eb8d06

4 files changed

Lines changed: 64 additions & 1 deletion

File tree

‎NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ PHP NEWS
2929
(Ilia Alshanetsky)
3030
. Fixed bug GH-23729 (DOMXPath::__construct() use-after-free during an
3131
evaluation). (David Carlier)
32+
. Fixed bug GH-23897 (php:function() assertion failure after a failed
33+
registerPHPFunctions()). (David Carlier)
3234

3335
- FTP:
3436
. Fixed bug GH-23619 (cryptic error on servers that don't support TLS

‎ext/dom/tests/gh23897.phpt‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-23897 (Assertion failure in php_dom_xpath_callback_dispatch() after failed registerPhpFunctions())
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
$dom = new DOMDocument();
8+
$dom->loadXML('<root/>');
9+
10+
$xpath = new DOMXPath($dom);
11+
$xpath->registerNamespace('php', 'http://php.net/xpath');
12+
try {
13+
$xpath->registerPhpFunctions('testPhpFunction');
14+
} catch (Throwable $e) {
15+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
16+
}
17+
try {
18+
var_dump($xpath->evaluate('php:function("testPhpFunction")'));
19+
} catch (Throwable $e) {
20+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
21+
}
22+
?>
23+
--EXPECT--
24+
TypeError: DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a callable, function "testPhpFunction" not found or invalid function name
25+
Error: No callbacks were registered

‎ext/dom/xpath_callbacks.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ static zend_result php_dom_xpath_callback_dispatch(php_dom_xpath_callbacks *xpat
407407
{
408408
zval callback_retval;
409409

410-
if (UNEXPECTED(ns == NULL)) {
410+
if (UNEXPECTED(ns == NULL || ns->mode == PHP_DOM_REG_FUNC_MODE_NONE)) {
411411
zend_throw_error(NULL, "No callbacks were registered");
412412
return FAILURE;
413413
}

‎ext/xsl/tests/gh23897.phpt‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-23897 (Assertion failure in php_dom_xpath_callback_dispatch() after failed registerPHPFunctions())
3+
--EXTENSIONS--
4+
xsl
5+
--CREDITS--
6+
YuanchengJiang
7+
--FILE--
8+
<?php
9+
$dom = new DOMDocument();
10+
$dom->loadXML('<root><level1/></root>');
11+
12+
$xsl = new DOMDocument();
13+
$xsl->loadXML(<<<XML
14+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
15+
<xsl:template match="root">
16+
<xsl:value-of select="php:function('testPhpFunction', .)" />
17+
</xsl:template>
18+
</xsl:stylesheet>
19+
XML);
20+
21+
$xslt = new XSLTProcessor();
22+
try {
23+
$xslt->registerPHPFunctions('testPhpFunction');
24+
} catch (Throwable $e) {
25+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
26+
}
27+
$xslt->importStylesheet($xsl);
28+
try {
29+
var_dump($xslt->transformToXml($dom));
30+
} catch (Throwable $e) {
31+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
32+
}
33+
?>
34+
--EXPECT--
35+
TypeError: XSLTProcessor::registerPHPFunctions(): Argument #1 ($functions) must be a callable, function "testPhpFunction" not found or invalid function name
36+
Error: No callbacks were registered

0 commit comments

Comments
 (0)