Fix for bug 527558 (Crash [@ xul.dll\!nsDependentCSubstring::nsDependentCSubstring]). r=sicking.
authorPeter Van der Beken <peterv@propagandism.org>
Sun, 15 Nov 2009 14:50:09 +0100
changeset 296021 d858d1b52b6b7c7834b166626f14fb27a23ec093
parent 296020 11c096c410a73a9d23637bc73c15557802e5f409
child 296022 9a7520bca4164fe441a12eaeac77f3b6db402194
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs527558
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Fix for bug 527558 (Crash [@ xul.dll\!nsDependentCSubstring::nsDependentCSubstring]). r=sicking.
dom/locales/en-US/chrome/xslt/xslt.properties
dom/xslt/crashtests/527558_1.xml
dom/xslt/crashtests/crashtests.list
dom/xslt/xpath/txIXPathContext.h
dom/xslt/xslt/txPatternParser.cpp
dom/xslt/xslt/txPatternParser.h
dom/xslt/xslt/txStylesheetCompileHandlers.cpp
dom/xslt/xslt/txStylesheetCompiler.cpp
dom/xslt/xslt/txStylesheetCompiler.h
xpcom/base/ErrorList.h
--- a/dom/locales/en-US/chrome/xslt/xslt.properties
+++ b/dom/locales/en-US/chrome/xslt/xslt.properties
@@ -28,11 +28,12 @@ 23 = XPath parse failure: ':' unexpected
 24 = XPath parse failure: '!' unexpected, negation is not():
 25 = XPath parse failure: illegal character found:
 26 = XPath parse failure: binary operator expected:
 27 = An XSLT stylesheet load was blocked for security reasons.
 28 = Evaluating an invalid expression.
 29 = Unbalanced curly brace.
 30 = Creating an element with an invalid QName.
 31 = Variable binding shadows variable binding within the same template.
+32 = Call to the key function not allowed.
 
 LoadingError = Error loading stylesheet: %S
 TransformError = Error during XSLT transformation: %S
new file mode 100644
--- /dev/null
+++ b/dom/xslt/crashtests/527558_1.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xml" href="#bug"?>
+<!DOCTYPE doc [
+<!ATTLIST xsl:transform
+  id	ID	#REQUIRED>
+]>
+<doc>
+<xsl:transform id="bug"
+                version="2.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:key name="k0" match="e1" use="key('k0', 'foobar')" /> 
+  <xsl:template id="t1" name="t1" match="key('k0', '1/2/2003')" />
+</xsl:transform>
+
+<e1 a1="foobar" a2="foobar"/>
+
+</doc>
--- a/dom/xslt/crashtests/crashtests.list
+++ b/dom/xslt/crashtests/crashtests.list
@@ -1,16 +1,17 @@
 load 91332.xml
 load 111994.xml
 load 182460-table.xhtml
 load 226425.xml
 load 406106-1.html
 load 483444.xml
 load 485217.xml
 load 485286.xml
+load 527558_1.xml
 load 528300.xml
 load 528488.xml
 load 528963.xml
 load 545927.html
 load 601543.html
 load 603844.html
 load 602115.html
 load 667315.xml
--- a/dom/xslt/xpath/txIXPathContext.h
+++ b/dom/xslt/xpath/txIXPathContext.h
@@ -46,16 +46,24 @@ public:
      * Should nametests parsed in this context be case-sensitive
      */
     virtual bool caseInsensitiveNameTests() = 0;
 
     /*
      * Callback to be used by the Parser if errors are detected.
      */
     virtual void SetErrorOffset(uint32_t aOffset) = 0;
+
+    enum Allowed {
+        KEY_FUNCTION = 1 << 0
+    };
+    virtual bool allowed(Allowed aAllowed)
+    {
+        return true;
+    }
 };
 
 /*
  * txIMatchContext
  *
  * Interface used for matching XSLT Patters.
  * This is the part of txIEvalContext (see below), that is independent
  * of the context node when evaluating a XPath expression, too.
--- a/dom/xslt/xslt/txPatternParser.cpp
+++ b/dom/xslt/xslt/txPatternParser.cpp
@@ -4,42 +4,45 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "txPatternParser.h"
 #include "txExprLexer.h"
 #include "nsGkAtoms.h"
 #include "nsError.h"
 #include "txStringUtils.h"
 #include "txXSLTPatterns.h"
-#include "txIXPathContext.h"
+#include "txStylesheetCompiler.h"
 #include "txPatternOptimizer.h"
 
 
-txPattern* txPatternParser::createPattern(const nsAFlatString& aPattern,
-                                          txIParseContext* aContext)
+nsresult txPatternParser::createPattern(const nsAFlatString& aPattern,
+                                        txIParseContext* aContext,
+                                        txPattern** aResult)
 {
     txExprLexer lexer;
     nsresult rv = lexer.parse(aPattern);
     if (NS_FAILED(rv)) {
         // XXX error report parsing error
-        return 0;
+        return rv;
     }
     nsAutoPtr<txPattern> pattern;
     rv = createUnionPattern(lexer, aContext, *getter_Transfers(pattern));
     if (NS_FAILED(rv)) {
         // XXX error report parsing error
-        return 0;
+        return rv;
     }
 
     txPatternOptimizer optimizer;
     txPattern* newPattern = nullptr;
     rv = optimizer.optimize(pattern, &newPattern);
-    NS_ENSURE_SUCCESS(rv, nullptr);
+    NS_ENSURE_SUCCESS(rv, rv);
 
-    return newPattern ? newPattern : pattern.forget();
+    *aResult = newPattern ? newPattern : pattern.forget();
+
+    return NS_OK;
 }
 
 nsresult txPatternParser::createUnionPattern(txExprLexer& aLexer,
                                              txIParseContext* aContext,
                                              txPattern*& aPattern)
 {
     nsresult rv = NS_OK;
     txPattern* locPath = 0;
@@ -241,16 +244,19 @@ nsresult txPatternParser::createKeyPatte
     if (aLexer.nextToken()->mType != Token::COMMA && 
         aLexer.peek()->mType != Token::LITERAL)
         return NS_ERROR_XPATH_PARSE_FAILURE;
     const nsDependentSubstring& value =
         aLexer.nextToken()->Value();
     if (aLexer.nextToken()->mType != Token::R_PAREN)
         return NS_ERROR_XPATH_PARSE_FAILURE;
 
+    if (!aContext->allowed(txIParseContext::KEY_FUNCTION))
+        return NS_ERROR_XSLT_CALL_TO_KEY_NOT_ALLOWED;
+
     const char16_t* colon;
     if (!XMLUtils::isValidQName(PromiseFlatString(key), &colon))
         return NS_ERROR_XPATH_PARSE_FAILURE;
     nsCOMPtr<nsIAtom> prefix, localName;
     int32_t namespaceID;
     nsresult rv = resolveQName(key, getter_AddRefs(prefix), aContext,
                                getter_AddRefs(localName), namespaceID);
     if (NS_FAILED(rv))
--- a/dom/xslt/xslt/txPatternParser.h
+++ b/dom/xslt/xslt/txPatternParser.h
@@ -4,21 +4,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef TX_PATTERNPARSER_H
 #define TX_PATTERNPARSER_H
 
 #include "txXSLTPatterns.h"
 #include "txExprParser.h"
 
+class txStylesheetCompilerState;
+
 class txPatternParser : public txExprParser
 {
 public:
-    static txPattern* createPattern(const nsAFlatString& aPattern,
-                                    txIParseContext* aContext);
+    static nsresult createPattern(const nsAFlatString& aPattern,
+                                  txIParseContext* aContext,
+                                  txPattern** aResult);
 protected:
     static nsresult createUnionPattern(txExprLexer& aLexer,
                                        txIParseContext* aContext,
                                        txPattern*& aPattern);
     static nsresult createLocPathPattern(txExprLexer& aLexer,
                                          txIParseContext* aContext,
                                          txPattern*& aPattern);
     static nsresult createIdPattern(txExprLexer& aLexer,
--- a/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
+++ b/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
@@ -178,17 +178,17 @@ getExprAttr(txStylesheetAttr* aAttribute
     nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
                                aName, aRequired, &attr);
     if (!attr) {
         return rv;
     }
 
     rv = txExprParser::createExpr(attr->mValue, &aState,
                                   getter_Transfers(aExpr));
-    if (NS_FAILED(rv) && aState.fcp()) {
+    if (NS_FAILED(rv) && aState.ignoreError(rv)) {
         // use default value in fcp for not required exprs
         if (aRequired) {
             aExpr = new txErrorExpr(
 #ifdef TX_TO_STRING
                                     attr->mValue
 #endif
                                     );
             NS_ENSURE_TRUE(aExpr, NS_ERROR_OUT_OF_MEMORY);
@@ -250,20 +250,21 @@ getPatternAttr(txStylesheetAttr* aAttrib
     aPattern = nullptr;
     txStylesheetAttr* attr = nullptr;
     nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
                                aName, aRequired, &attr);
     if (!attr) {
         return rv;
     }
 
-    aPattern = txPatternParser::createPattern(attr->mValue, &aState);
-    if (!aPattern && (aRequired || !aState.fcp())) {
+    rv = txPatternParser::createPattern(attr->mValue, &aState,
+                                        getter_Transfers(aPattern));
+    if (NS_FAILED(rv) && (aRequired || !aState.ignoreError(rv))) {
         // XXX ErrorReport: XSLT-Pattern parse failure
-        return NS_ERROR_XPATH_PARSE_FAILURE;
+        return rv;
     }
 
     return NS_OK;
 }
 
 static nsresult
 getNumberAttr(txStylesheetAttr* aAttributes,
               int32_t aAttrCount,
@@ -833,26 +834,30 @@ txFnStartKey(int32_t aNamespaceID,
              txStylesheetCompilerState& aState)
 {
     nsresult rv = NS_OK;
     txExpandedName name;
     rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
                       aState, name);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    aState.mDisAllowed = txIParseContext::KEY_FUNCTION;
+
     nsAutoPtr<txPattern> match;
     rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, true,
                         aState, match);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoPtr<Expr> use;
     rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::use, true,
                      aState, use);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    aState.mDisAllowed = 0;
+
     rv = aState.mStylesheet->addKey(name, Move(match), Move(use));
     NS_ENSURE_SUCCESS(rv, rv);
     
     return aState.pushHandlerTable(gTxIgnoreHandler);
 }
 
 static nsresult
 txFnEndKey(txStylesheetCompilerState& aState)
--- a/dom/xslt/xslt/txStylesheetCompiler.cpp
+++ b/dom/xslt/xslt/txStylesheetCompiler.cpp
@@ -523,16 +523,17 @@ txStylesheetCompiler::maybeDoneCompiling
  */
 
 
 txStylesheetCompilerState::txStylesheetCompilerState(txACompileObserver* aObserver)
     : mHandlerTable(nullptr),
       mSorter(nullptr),
       mDOE(false),
       mSearchingForFallback(false),
+      mDisAllowed(0),
       mObserver(aObserver),
       mEmbedStatus(eNoEmbed),
       mDoneWithThisStylesheet(false),
       mNextInstrPtr(nullptr),
       mToplevelIterator(nullptr)
 {
     // Embedded stylesheets have another handler, which is set in
     // txStylesheetCompiler::init if the baseURI has a fragment identifier.
@@ -918,16 +919,19 @@ TX_ConstructXSLTFunction(nsIAtom* aName,
                          txStylesheetCompilerState* aState,
                          FunctionCall** aFunction)
 {
     if (aName == nsGkAtoms::document) {
         *aFunction =
             new DocumentFunctionCall(aState->mElementContext->mBaseURI);
     }
     else if (aName == nsGkAtoms::key) {
+        if (!aState->allowed(txIParseContext::KEY_FUNCTION)) {
+            return NS_ERROR_XSLT_CALL_TO_KEY_NOT_ALLOWED;
+        }
         *aFunction =
             new txKeyFunctionCall(aState->mElementContext->mMappings);
     }
     else if (aName == nsGkAtoms::formatNumber) {
         *aFunction =
             new txFormatNumberFunctionCall(aState->mStylesheet,
                                            aState->mElementContext->mMappings);
     }
--- a/dom/xslt/xslt/txStylesheetCompiler.h
+++ b/dom/xslt/xslt/txStylesheetCompiler.h
@@ -135,26 +135,40 @@ public:
      */
     bool fcp()
     {
         return mElementContext->mForwardsCompatibleParsing;
     }
 
     void SetErrorOffset(uint32_t aOffset) override;
 
+    bool allowed(Allowed aAllowed) override
+    {
+        return !(mDisAllowed & aAllowed);
+    }
+
+    bool ignoreError(nsresult aResult)
+    {
+        // Some errors shouldn't be ignored even in forwards compatible parsing
+        // mode.
+        return aResult != NS_ERROR_XSLT_CALL_TO_KEY_NOT_ALLOWED &&
+               fcp();
+    }
+
     static void shutdown();
 
 
     nsRefPtr<txStylesheet> mStylesheet;
     txHandlerTable* mHandlerTable;
     nsAutoPtr<txElementContext> mElementContext;
     txPushNewContext* mSorter;
     nsAutoPtr<txList> mChooseGotoList;
     bool mDOE;
     bool mSearchingForFallback;
+    uint16_t mDisAllowed;
 
 protected:
     nsRefPtr<txACompileObserver> mObserver;
     nsTArray<txInScopeVariable*> mInScopeVariables;
     nsTArray<txStylesheetCompiler*> mChildCompilerList;
     // embed info, target information is the ID
     nsString mTarget;
     enum 
--- a/xpcom/base/ErrorList.h
+++ b/xpcom/base/ErrorList.h
@@ -783,16 +783,17 @@
   ERROR(NS_ERROR_XPATH_BAD_BANG,                      FAILURE(24)),
   ERROR(NS_ERROR_XPATH_ILLEGAL_CHAR,                  FAILURE(25)),
   ERROR(NS_ERROR_XPATH_BINARY_EXPECTED,               FAILURE(26)),
   ERROR(NS_ERROR_XSLT_LOAD_BLOCKED_ERROR,             FAILURE(27)),
   ERROR(NS_ERROR_XPATH_INVALID_EXPRESSION_EVALUATED,  FAILURE(28)),
   ERROR(NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE,        FAILURE(29)),
   ERROR(NS_ERROR_XSLT_BAD_NODE_NAME,                  FAILURE(30)),
   ERROR(NS_ERROR_XSLT_VAR_ALREADY_SET,                FAILURE(31)),
+  ERROR(NS_ERROR_XSLT_CALL_TO_KEY_NOT_ALLOWED,        FAILURE(32)),
 
   ERROR(NS_XSLT_GET_NEW_HANDLER,  SUCCESS(1)),
 #undef MODULE
 
 
   /* ======================================================================= */
   /* 28: NS_ERROR_MODULE_IPC */
   /* ======================================================================= */