Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ PHP NEWS
. Fixed xml_get_current_byte_index() returning negative values for byte
indexes beyond 2 GiB on Windows x64. (Marc Bennewitz)

- XSL:
. Fixed a use-after-free when a transformation was started on a processor
that is already transforming. (Ilia Alshanetsky)

- Zlib:
. Fixed inflate_init() dropping the preset dictionary for raw streams with
a non-default window. (Ilia Alshanetsky)
Expand Down
7 changes: 7 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ PHP 8.7 UPGRADE NOTES
to 16 by default. Set the stream context option max_filter_count to change
this.

- XSL:
. XSLTProcessor::transformToDoc(), XSLTProcessor::transformToUri() and
XSLTProcessor::transformToXml() now throw an Error when called while the
same processor is already transforming, for example from a php:function()
callback or from a suspended Fiber. Use a separate XSLTProcessor instance
instead.

========================================
2. New Features
========================================
Expand Down
100 changes: 100 additions & 0 deletions ext/xsl/tests/xsltprocessor_nested_transform.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
--TEST--
XSLTProcessor refuses a nested transformation on the same processor
--EXTENSIONS--
dom
xsl
--FILE--
<?php

function nested($nodes) {
static $called = false;
if ($called) {
return 'v';
}
$called = true;
$proc = $GLOBALS['proc'];
$doc = $GLOBALS['doc'];
try {
var_dump($proc->transformToXml($doc));
} catch (Error $e) {
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
}
try {
var_dump($proc->transformToDoc($doc));
} catch (Error $e) {
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
}
try {
var_dump($proc->transformToUri($doc, $GLOBALS['uri']));
} catch (Error $e) {
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
}
return 'v';
}

function suspend($nodes) {
Fiber::suspend();
return 'f';
}

function text($nodes) {
return $nodes[0]->textContent;
}

$doc = new DOMDocument();
$doc->loadXML('<root><a>1</a><b>2</b><c>3</c></root>');

$xsl = new DOMDocument();
$xsl->loadXML(<<<XML
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:key name="k" match="*" use="name()"/>
<xsl:param name="cb" select="'nested'"/>
<xsl:template match="/"><xsl:for-each select="/root/*">[<xsl:value-of select="php:function(\$cb, .)"/><xsl:value-of select="name(key('k', name(.)))"/>]</xsl:for-each></xsl:template>
</xsl:stylesheet>
XML);

$uri = __DIR__ . '/xsltprocessor_nested_transform.xml';

$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStylesheet($xsl);

var_dump($proc->transformToXml($doc));

$proc->setParameter('', 'cb', 'suspend');
$fiber = new Fiber(fn () => $proc->transformToXml($doc));
$fiber->start();
try {
var_dump($proc->transformToXml($doc));
} catch (Error $e) {
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
}
while (!$fiber->isTerminated()) {
$fiber->resume();
}
var_dump($fiber->getReturn());

$proc->setParameter('', 'cb', 'text');
var_dump($proc->transformToXml($doc));
var_dump($proc->transformToDoc($doc)->textContent);

?>
--CLEAN--
<?php
@unlink(__DIR__ . '/xsltprocessor_nested_transform.xml');
?>
--EXPECT--
Error: Cannot call XSLTProcessor::transformToXml() while a transformation is in progress
Error: Cannot call XSLTProcessor::transformToDoc() while a transformation is in progress
Error: Cannot call XSLTProcessor::transformToUri() while a transformation is in progress
string(35) "<?xml version="1.0"?>
[va][vb][vc]
"
Error: Cannot call XSLTProcessor::transformToXml() while a transformation is in progress
string(35) "<?xml version="1.0"?>
[fa][fb][fc]
"
string(35) "<?xml version="1.0"?>
[1a][2b][3c]
"
string(12) "[1a][2b][3c]"
7 changes: 7 additions & 0 deletions ext/xsl/xsltprocessor.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,13 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
return NULL;
}

if (UNEXPECTED(intern->transform_depth > 0)) {
zend_string *name = get_active_function_or_method_name();
zend_throw_error(NULL, "Cannot call %s() while a transformation is in progress", ZSTR_VAL(name));
zend_string_release(name);
return NULL;
}

intern->transform_depth++;

if (intern->profiling) {
Expand Down
Loading