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 179461 9e43ff213b6454ff835a6990aa0498e663914881
parent 179460 d80b56079e66317ec4fe36c0a615169ed4d20d08
child 179462 b2a47bd7d0df3a65ec0057e0c9625adf4a0417ec
push id42516
push usersean.stangl@gmail.com
push dateMon, 21 Apr 2014 20:27:50 +0000
treeherdermozilla-inbound@9e43ff213b64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmjrosenb
bugs616491
milestone31.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
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;