Project

Profile

Help

Bug #3200

closed

StackOverflow (infinite recursion in optimizer)

Added by Radu Coravu about 7 years ago. Updated almost 7 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Internals
Sprint/Milestone:
-
Start date:
2017-04-13
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
9.7
Fix Committed on Branch:
9.7, trunk
Fixed in Maintenance Release:
Platforms:

Description

The XSLT looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:template match="/">
        <results>
            <xsl:for-each select="1 to 3">
                <xsl:variable name="pos" select="position()"/>
                <xsl:for-each select="7 to 9">
                    <xsl:element name="test">
                        <xsl:attribute name="xml:id" select="concat('hi', string($pos))"/>
                    </xsl:element>
                </xsl:for-each>
            </xsl:for-each>
        </results>
    </xsl:template>
</xsl:stylesheet>

and if it is applied to any XML you get this:

java.lang.StackOverflowError
	at java.util.AbstractList.iterator(Unknown Source)
	at net.sf.saxon.expr.Expression.optimizeChildren(Expression.java:514)
	at net.sf.saxon.expr.FunctionCall.optimize(FunctionCall.java:248)
	at net.sf.saxon.expr.SystemFunctionCall.optimize(SystemFunctionCall.java:158)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.Expression.optimizeChildren(Expression.java:515)
	at net.sf.saxon.expr.instruct.SimpleNodeConstructor.optimize(SimpleNodeConstructor.java:163)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.Expression.optimizeChildren(Expression.java:515)
	at net.sf.saxon.expr.instruct.ParentNodeConstructor.optimize(ParentNodeConstructor.java:206)
	at net.sf.saxon.expr.instruct.FixedElement.optimize(FixedElement.java:108)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:248)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
	at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:311)
	at net.sf.saxon.expr.instruct.ForEach.optimize(ForEach.java:273)
	at net.sf.saxon.expr.Operand.optimize(Operand.java:200)

Actions #1

Updated by Radu Coravu about 7 years ago

Adding link to Oxygen forum where this was first reported:

https://www.oxygenxml.com/forum/post42413.html#p42413

Actions #2

Updated by Michael Kay about 7 years ago

  • Subject changed from StackOverflow to StackOverflow (infinite recursion in optimizer)
  • Category set to Internals
  • Assignee set to Michael Kay
Actions #3

Updated by Michael Kay about 7 years ago

  • Applies to branch 9.7 added

Applies to 9.7 only: the problem is in the loop-lifting optimization which has been rewritten for 9.8

Actions #4

Updated by Radu Coravu about 7 years ago

Thanks for looking into this. Any hint how I could patch this for the Saxon 9.7 bundled with Oxygen 19.0? Any particular class containing the particular fix that I could use as a patch.

Also I'm not sure if you saw that but I also requested this issue to be reopened:

https://saxonica.plan.io/issues/3068

as it produces some invalid XML docs when having attributes like xml:space set as default attributes in the XML Schema..

Actions #5

Updated by Michael Kay about 7 years ago

The problem is in FixedAttribute.setSelect() and is specific to the case where the attribute name is xml:id; the code is wrapping a call of normalize-space() around the select expression; if the select expression XX is focus-independent it then attempts to loop-lift the call of normalize-space(XX), and this attempt has the side-effect of wrapping another call of normalize-space() around the new select expression, ad infinitum.

Actions #6

Updated by Michael Kay about 7 years ago

  • Status changed from New to In Progress
Actions #7

Updated by Michael Kay about 7 years ago

The problem can be fixed by moving the code that adds the call on normalize-space() from the FixedAttribute.setSelect() method to FixedAttribute.localTypeCheck(). Question is, does this have any unwanted side-effects?

Actions #8

Updated by Radu Coravu about 7 years ago

Well, we could unleash it on all the innocent Oxygen users and find out :)

I can initially make a fix on my side and then see what XSLT-related automated tests that we have fail tomorrow.

Could you run the tests that you have for Saxon with this change in place?

Actions #9

Updated by Radu Coravu about 7 years ago

So the code at the end of "net.sf.saxon.expr.instruct.FixedAttribute.localTypeCheck(ExpressionVisitor, ContextItemStaticInfo)" would change to something like this:

        Expression select = getSelect();
        if (select instanceof StringLiteral) {
            boolean special = false;
            // If attribute name is xml:id, add whitespace normalization
            if (nodeName.equals(StandardNames.XML_ID_NAME)) {
                select = SystemFunction.makeCall("normalize-space", getRetainedStaticContext(), select);
            }
            CharSequence val = ((StringLiteral) select).getStringValue();
            for (int k = 0; k < val.length(); k++) {
                char c = val.charAt(k);
                if ((int) c < 33 || (int) c > 126 ||
                        c == '<' || c == '>' || c == '&' || c == '\"') {
                    special = true;
                    break;
                }
            }
            if (!special) {
                setNoSpecialChars();
            }
        }

right?

ADDED BY MHK: No, I don't think it's correct to do this only when the value is a literal. Please see the patch I'm committing.

Actions #10

Updated by Michael Kay about 7 years ago

  • Status changed from In Progress to Resolved
  • Fix Committed on Branch 9.7, 9.8 added

The fix seems to be OK as far as I can tell - there will be more regression testing when we do a maintenance release build.

Committing on the 9.7 and 9.8 branches even though the problem manifests itself only on 9.7.

Actions #11

Updated by Radu Coravu about 7 years ago

Ok, I'll report back here if I find anything wrong with the fix in our automated tests...

Actions #12

Updated by O'Neil Delpratt almost 7 years ago

  • Fix Committed on Branch trunk added
  • Fix Committed on Branch deleted (9.8)
Actions #13

Updated by O'Neil Delpratt almost 7 years ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 9.7.0.19 added

Bug fix applied in the 9.7.0.19 maintenance release.

Please register to edit this issue

Also available in: Atom PDF