Merge branch 'PHP-8.1' into PHP-8.2

* PHP-8.1:
  Fix validation logic of php:function() callbacks in dom and xsl
This commit is contained in:
Niels Dossche 2023-11-02 20:32:10 +01:00
commit 304e482813
5 changed files with 90 additions and 4 deletions

2
NEWS
View File

@ -16,6 +16,7 @@ PHP NEWS
- DOM: - DOM:
. Fix registerNodeClass with abstract class crashing. (nielsdos) . Fix registerNodeClass with abstract class crashing. (nielsdos)
. Add missing NULL pointer error check. (icy17) . Add missing NULL pointer error check. (icy17)
. Fix validation logic of php:function() callbacks. (nielsdos)
- Fiber: - Fiber:
. Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi)
@ -65,6 +66,7 @@ PHP NEWS
- XSL: - XSL:
. Add missing module dependency. (nielsdos) . Add missing module dependency. (nielsdos)
. Fix validation logic of php:function() callbacks. (nielsdos)
26 Oct 2023, PHP 8.2.12 26 Oct 2023, PHP 8.2.12

View File

@ -0,0 +1,27 @@
--TEST--
php:function() edge cases
--EXTENSIONS--
dom
--FILE--
<?php
$doc = new DOMDocument();
$doc->loadHTML('<a href="https://php.net">hello</a>');
$xpath = new DOMXpath($doc);
$xpath->registerNamespace("php", "http://php.net/xpath");
$xpath->registerPHPFunctions();
try {
$xpath->query("//a[php:function(3)]");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
try {
$xpath->query("//a[php:function()]");
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Handler name must be a string
Function name must be passed as the first argument

View File

@ -70,12 +70,17 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs,
return; return;
} }
if (UNEXPECTED(nargs == 0)) {
zend_throw_error(NULL, "Function name must be passed as the first argument");
return;
}
fci.param_count = nargs - 1; fci.param_count = nargs - 1;
if (fci.param_count > 0) { if (fci.param_count > 0) {
fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0); fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0);
} }
/* Reverse order to pop values off ctxt stack */ /* Reverse order to pop values off ctxt stack */
for (i = nargs - 2; i >= 0; i--) { for (i = fci.param_count - 1; i >= 0; i--) {
obj = valuePop(ctxt); obj = valuePop(ctxt);
switch (obj->type) { switch (obj->type) {
case XPATH_STRING: case XPATH_STRING:
@ -128,11 +133,12 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs,
fci.size = sizeof(fci); fci.size = sizeof(fci);
/* Last element of the stack is the function name */
obj = valuePop(ctxt); obj = valuePop(ctxt);
if (obj->stringval == NULL) { if (obj->stringval == NULL) {
zend_type_error("Handler name must be a string"); zend_type_error("Handler name must be a string");
xmlXPathFreeObject(obj); xmlXPathFreeObject(obj);
goto cleanup; goto cleanup_no_callable;
} }
ZVAL_STRING(&fci.function_name, (char *) obj->stringval); ZVAL_STRING(&fci.function_name, (char *) obj->stringval);
xmlXPathFreeObject(obj); xmlXPathFreeObject(obj);
@ -177,6 +183,7 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs,
cleanup: cleanup:
zend_string_release_ex(callable, 0); zend_string_release_ex(callable, 0);
zval_ptr_dtor_nogc(&fci.function_name); zval_ptr_dtor_nogc(&fci.function_name);
cleanup_no_callable:
if (fci.param_count > 0) { if (fci.param_count > 0) {
for (i = 0; i < nargs - 1; i++) { for (i = 0; i < nargs - 1; i++) {
zval_ptr_dtor(&fci.params[i]); zval_ptr_dtor(&fci.params[i]);

View File

@ -0,0 +1,45 @@
--TEST--
php:function() edge cases
--EXTENSIONS--
xsl
--FILE--
<?php
function test($input) {
$xsl = new DomDocument();
$xsl->loadXML('<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl">
<xsl:template match="/">
<xsl:value-of select="php:function(' . $input . ')" />
</xsl:template>
</xsl:stylesheet>');
$inputdom = new DomDocument();
$inputdom->loadXML('<?xml version="1.0" encoding="iso-8859-1" ?>
<today></today>');
$proc = new XsltProcessor();
$proc->registerPhpFunctions();
$xsl = $proc->importStylesheet($xsl);
try {
$proc->transformToDoc($inputdom);
} catch (Exception $e) {
echo $e->getMessage(), "\n";
}
}
try {
test("");
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
test("3");
?>
--EXPECTF--
Function name must be passed as the first argument
Warning: XSLTProcessor::transformToDoc(): Handler name must be a string in %s on line %d

View File

@ -141,12 +141,17 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
return; return;
} }
if (UNEXPECTED(nargs == 0)) {
zend_throw_error(NULL, "Function name must be passed as the first argument");
return;
}
fci.param_count = nargs - 1; fci.param_count = nargs - 1;
if (fci.param_count > 0) { if (fci.param_count > 0) {
args = safe_emalloc(fci.param_count, sizeof(zval), 0); args = safe_emalloc(fci.param_count, sizeof(zval), 0);
} }
/* Reverse order to pop values off ctxt stack */ /* Reverse order to pop values off ctxt stack */
for (i = nargs - 2; i >= 0; i--) { for (i = fci.param_count - 1; i >= 0; i--) {
obj = valuePop(ctxt); obj = valuePop(ctxt);
if (obj == NULL) { if (obj == NULL) {
ZVAL_NULL(&args[i]); ZVAL_NULL(&args[i]);
@ -221,7 +226,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
fci.params = NULL; fci.params = NULL;
} }
/* Last element of the stack is the function name */
obj = valuePop(ctxt); obj = valuePop(ctxt);
if (obj == NULL || obj->stringval == NULL) { if (obj == NULL || obj->stringval == NULL) {
php_error_docref(NULL, E_WARNING, "Handler name must be a string"); php_error_docref(NULL, E_WARNING, "Handler name must be a string");