Bug 616491 - Follow-up: detect over-recursion on Windows. r=mjrosenb
☠☠ backed out by 190102c75df0 ☠ ☠
authorSean Stangl <sstangl@mozilla.com>
Tue, 08 Apr 2014 13:51:37 -0700
changeset 179867 9e43ff213b6454ff835a6990aa0498e663914881
parent 179866 d80b56079e66317ec4fe36c0a615169ed4d20d08
child 179868 b2a47bd7d0df3a65ec0057e0c9625adf4a0417ec
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmjrosenb
bugs616491
milestone31.0a1
Bug 616491 - Follow-up: detect over-recursion on Windows. r=mjrosenb
js/src/yarr/YarrPattern.cpp
--- a/js/src/yarr/YarrPattern.cpp
+++ b/js/src/yarr/YarrPattern.cpp
@@ -299,16 +299,32 @@ public:
         m_pattern.reset();
         m_characterClassConstructor.reset();
 
         m_pattern.m_body = newOrCrash<PatternDisjunction>();
         m_alternative = m_pattern.m_body->addNewAlternative();
         m_pattern.m_disjunctions.append(m_pattern.m_body);
     }
 
+    void setStackBase(uint8_t *stackBase) {
+        m_stackBase = stackBase;
+    }
+
+    bool isOverRecursed() {
+        /*
+         * Bug 616491: attempt detection of over-recursion.
+         * "256KB should be enough stack for anyone."
+         */
+        uint8_t stackDummy_;
+        JS_ASSERT(m_stackBase != nullptr);
+        if (m_stackBase - &stackDummy > (1 << 18))
+            return true;
+        return false;
+    }
+
     void assertionBOL()
     {
         if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) {
             m_alternative->m_startsWithBOL = true;
             m_alternative->m_containsBOL = true;
             m_pattern.m_containsBOL = true;
         }
         m_alternative->m_terms.append(PatternTerm::BOL());
@@ -569,22 +585,17 @@ public:
     void disjunction()
     {
         m_alternative = m_alternative->m_parent->addNewAlternative();
     }
 
     ErrorCode setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition,
                                       unsigned *callFrameSizeOut)
     {
-        /*
-         * Attempt detection of over-recursion:
-         * "1MB should be enough stack for anyone."
-         */
-        uint8_t stackDummy_;
-        if (m_stackBase - &stackDummy_ > 1024*1024)
+        if (isOverRecursed())
             return PatternTooLarge;
 
         alternative->m_hasFixedSize = true;
         Checked<unsigned> currentInputPosition = initialInputPosition;
 
         for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
             PatternTerm& term = alternative->m_terms[i];
 
@@ -669,16 +680,19 @@ public:
 
         alternative->m_minimumSize = (currentInputPosition - initialInputPosition).unsafeGet();
         *callFrameSizeOut = currentCallFrameSize;
         return NoError;
     }
 
     ErrorCode setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned *maximumCallFrameSizeOut)
     {
+        if (isOverRecursed())
+            return PatternTooLarge;
+
         if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
             initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative;
 
         unsigned minimumInputSize = UINT_MAX;
         unsigned maximumCallFrameSize = 0;
         bool hasFixedSize = true;
 
         for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
@@ -845,33 +859,32 @@ public:
 
                 terms.append(PatternTerm(startsWithBOL, endsWithEOL));
 
                 m_pattern.m_containsBOL = false;
             }
         }
     }
 
-    void setStackBase(uint8_t *stackBase) {
-        m_stackBase = stackBase;
-    }
-
 private:
     YarrPattern& m_pattern;
     uint8_t * m_stackBase;
     PatternAlternative* m_alternative;
     CharacterClassConstructor m_characterClassConstructor;
     bool m_invertCharacterClass;
     bool m_invertParentheticalAssertion;
 };
 
 ErrorCode YarrPattern::compile(const String& patternString)
 {
     YarrPatternConstructor constructor(*this);
 
+    uint8_t stackDummy_;
+    constructor.setStackBase(&stackDummy_);
+
     if (ErrorCode error = parse(constructor, patternString))
         return error;
 
     // If the pattern contains illegal backreferences reset & reparse.
     // Quoting Netscape's "What's new in JavaScript 1.2",
     //      "Note: if the number of left parentheses is less than the number specified
     //       in \#, the \# is taken as an octal escape as described in the next row."
     if (containsIllegalBackReference()) {
@@ -882,19 +895,16 @@ ErrorCode YarrPattern::compile(const Str
         ErrorCode error =
 #endif
             parse(constructor, patternString, numSubpatterns);
 
         ASSERT(!error);
         ASSERT(numSubpatterns == m_numSubpatterns);
     }
 
-    uint8_t stackDummy_;
-    constructor.setStackBase(&stackDummy_);
-
     constructor.checkForTerminalParentheses();
     constructor.optimizeDotStarWrappedExpressions();
     constructor.optimizeBOL();
 
     if (ErrorCode error = constructor.setupOffsets())
         return error;
 
     return NoError;