-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Implement request #71571: XSLT processor should provide option to change maxDepth #13731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
--TEST-- | ||
Request #71571 (XSLT processor should provide option to change maxDepth) - variant A | ||
--EXTENSIONS-- | ||
xsl | ||
--INI-- | ||
error_reporting=E_ALL | ||
--FILE-- | ||
<?php | ||
|
||
$myxsl = <<<'EOF' | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||
<xsl:template match="/"> | ||
<xsl:call-template name="recurse"/> | ||
</xsl:template> | ||
|
||
<xsl:template name="recurse"> | ||
<xsl:call-template name="recurse"/> | ||
</xsl:template> | ||
</xsl:stylesheet> | ||
EOF; | ||
|
||
$xsl = new DOMDocument(); | ||
$xsl->loadXML($myxsl); | ||
|
||
$doc = new DOMDocument(); | ||
|
||
$proc = new XSLTProcessor; | ||
$proc->maxTemplateDepth = 2; | ||
$proc->importStyleSheet($xsl); | ||
$proc->transformToDoc($doc); | ||
|
||
?> | ||
--EXPECTF-- | ||
Warning: XSLTProcessor::transformToDoc(): runtime error: file %s line 8 element call-template in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): xsltApplySequenceConstructor: A potential infinite template recursion was detected. | ||
You can adjust xsltMaxDepth (--maxdepth) in order to raise the maximum number of nested template calls and variables/params (currently set to 2). in %s on line %d | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to change this error message? It would be nice to refer to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, done that now, albeit a bit ugly code. |
||
Warning: XSLTProcessor::transformToDoc(): Templates: in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #0 name recurse in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #1 name recurse in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #2 name / in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): Variables: in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
--TEST-- | ||
Request #71571 (XSLT processor should provide option to change maxDepth) - variant B | ||
--EXTENSIONS-- | ||
xsl | ||
--INI-- | ||
error_reporting=E_ALL | ||
--FILE-- | ||
<?php | ||
|
||
$myxsl = <<<'EOF' | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||
<xsl:template match="/"> | ||
<xsl:call-template name="recurse"/> | ||
</xsl:template> | ||
|
||
<xsl:template name="recurse"> | ||
<xsl:param name="COUNT">1</xsl:param> | ||
<xsl:call-template name="recurse"> | ||
<xsl:with-param name="COUNT" select="$COUNT + 1"/> | ||
</xsl:call-template> | ||
</xsl:template> | ||
</xsl:stylesheet> | ||
EOF; | ||
|
||
$xsl = new DOMDocument(); | ||
$xsl->loadXML($myxsl); | ||
|
||
$doc = new DOMDocument(); | ||
|
||
$proc = new XSLTProcessor; | ||
// Set the template depth limit so high that we will certainly hit the variable depth limit first. | ||
$proc->maxTemplateDepth = 2**30; | ||
$proc->maxTemplateVars = 2; | ||
$proc->importStyleSheet($xsl); | ||
$proc->transformToDoc($doc); | ||
|
||
?> | ||
--EXPECTF-- | ||
Warning: XSLTProcessor::transformToDoc(): runtime error: file %s line 8 element param in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): xsltApplyXSLTTemplate: A potential infinite template recursion was detected. | ||
You can adjust maxTemplateVars (--maxvars) in order to raise the maximum number of variables/params (currently set to 2). in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): Templates: in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #0 name recurse in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #1 name recurse in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #2 name / in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): Variables: in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #0 in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): COUNT in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): #1 in %s on line %d | ||
|
||
Warning: XSLTProcessor::transformToDoc(): param COUNT in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--TEST-- | ||
XSLTProcessor::$maxTemplateDepth errors | ||
--EXTENSIONS-- | ||
xsl | ||
--INI-- | ||
error_reporting=E_ALL & ~E_DEPRECATED | ||
--FILE-- | ||
<?php | ||
|
||
$processor = new XSLTProcessor; | ||
$oldValue = $processor->maxTemplateDepth; | ||
|
||
try { | ||
$processor->maxTemplateDepth = -1; | ||
} catch (ValueError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
var_dump($processor->maxTemplateDepth === $oldValue); | ||
|
||
try { | ||
$processor->maxTemplateDepth = -32.1; | ||
} catch (ValueError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
var_dump($processor->maxTemplateDepth === $oldValue); | ||
|
||
try { | ||
$processor->maxTemplateDepth = "-1"; | ||
} catch (ValueError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
var_dump($processor->maxTemplateDepth === $oldValue); | ||
|
||
?> | ||
--EXPECT-- | ||
XSLTProcessor::$maxTemplateDepth must be greater than or equal to 0 | ||
bool(true) | ||
XSLTProcessor::$maxTemplateDepth must be greater than or equal to 0 | ||
bool(true) | ||
XSLTProcessor::$maxTemplateDepth must be greater than or equal to 0 | ||
bool(true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--TEST-- | ||
XSLTProcessor::$maxTemplateVars errors | ||
--EXTENSIONS-- | ||
xsl | ||
--INI-- | ||
error_reporting=E_ALL & ~E_DEPRECATED | ||
--FILE-- | ||
<?php | ||
|
||
$processor = new XSLTProcessor; | ||
$oldValue = $processor->maxTemplateVars; | ||
|
||
try { | ||
$processor->maxTemplateVars = -1; | ||
} catch (ValueError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
var_dump($processor->maxTemplateVars === $oldValue); | ||
|
||
try { | ||
$processor->maxTemplateVars = -32.1; | ||
} catch (ValueError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
var_dump($processor->maxTemplateVars === $oldValue); | ||
|
||
try { | ||
$processor->maxTemplateVars = "-1"; | ||
} catch (ValueError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
var_dump($processor->maxTemplateVars === $oldValue); | ||
|
||
?> | ||
--EXPECT-- | ||
XSLTProcessor::$maxTemplateVars must be greater than or equal to 0 | ||
bool(true) | ||
XSLTProcessor::$maxTemplateVars must be greater than or equal to 0 | ||
bool(true) | ||
XSLTProcessor::$maxTemplateVars must be greater than or equal to 0 | ||
bool(true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--TEST-- | ||
XSLTProcessor: new instance without constructor | ||
--EXTENSIONS-- | ||
xsl | ||
--FILE-- | ||
<?php | ||
|
||
$rc = new ReflectionClass('XSLTProcessor'); | ||
$processor = $rc->newInstanceWithoutConstructor(); | ||
var_dump($processor); | ||
|
||
?> | ||
--EXPECTF-- | ||
object(XSLTProcessor)#2 (4) { | ||
["doXInclude"]=> | ||
bool(false) | ||
["cloneDocument"]=> | ||
bool(false) | ||
["maxTemplateDepth"]=> | ||
int(%d) | ||
["maxTemplateVars"]=> | ||
int(%d) | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love that you are using std properties, but unfortunately you need to override other handlers to really prevent non-validated mutations:
Override
.unset_property
,.get_property_ptr_ptr
, and.read_property
to preventunset()
,$obj->prop = &$ref
, and$ref = &$obj->prop
.Something like this should work:
Also, the engine may skip handlers once
cache_slot
has been filled:so you need to clear it in
xsl_objects_write_property_with_validation
withCACHE_PTR_EX(cache_slot, NULL);
afterzend_std_write_property()
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right of course, can't believe I missed this. Thanks for pointing this out!
On the one hand, it does make me wonder if all the extra code is "worth it", or if we should just throw at evaluation time. On the other hand I like to get an error as soon as I do something wrong, so I still prefer this from a UX PoV.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. That's a perfect use-case for hooks, and if they pass it may be possible to replace the custom handlers by a hook!