Reviewers: Erik Corry,

Message:
In some cases the recursion to gather Boyer-Moore info can cause a stack
overflow.

PTAL.

Description:
Limit recursion depth for gathering BoyerMoore info.


BUG=126412
TEST=regress-126412


Please review this at http://codereview.chromium.org/10380028/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/jsregexp.h
  M src/jsregexp.cc
  A test/mjsunit/regress/regress-126412.js


Index: src/jsregexp.cc
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 3455abce2399b3030a172e10ce1e2eb463f43647..cbfe18f4abed2d1ec310043adbd7b7e82072f2b6 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -997,7 +997,7 @@ RegExpEngine::CompilationResult RegExpCompiler::Assemble(

   bool use_slow_safe_regexp_compiler = false;
   if (heap->total_regexp_code_generated() >
-          RegExpImpl::kRegWxpCompiledLimit &&
+          RegExpImpl::kRegExpCompiledLimit &&
       heap->isolate()->memory_allocator()->SizeExecutable() >
           RegExpImpl::kRegExpExecutableMemoryLimit) {
     use_slow_safe_regexp_compiler = true;
@@ -3477,7 +3477,8 @@ void BoyerMoorePositionInfo::SetAll() {
 BoyerMooreLookahead::BoyerMooreLookahead(
     int length, RegExpCompiler* compiler)
     : length_(length),
-      compiler_(compiler) {
+      compiler_(compiler),
+      depth_(0) {
   if (compiler->ascii()) {
     max_char_ = String::kMaxAsciiCharCode;
   } else {
@@ -5588,6 +5589,11 @@ STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize ==
 void ChoiceNode::FillInBMInfo(
     int offset, BoyerMooreLookahead* bm, bool not_at_start) {
   ZoneList<GuardedAlternative>* alts = alternatives();
+  if (bm->MaxDepthExceeded()) {
+    bm->SetRest(offset);  // Give up trying to fill in info.
+    SaveBMInfo(bm, not_at_start, offset);
+    return;
+  }
   for (int i = 0; i < alts->length(); i++) {
     GuardedAlternative& alt = alts->at(i);
     if (alt.guards() != NULL && alt.guards()->length() != 0) {
Index: src/jsregexp.h
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 20313ca559ff1dff6a47c4dd86879a64b6451dc5..3f7bbdf4546cba286c9daf20dd7394028b3899e2 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -185,7 +185,7 @@ class RegExpImpl {
// total regexp code compiled including code that has subsequently been freed
   // and the total executable memory at any point.
   static const int kRegExpExecutableMemoryLimit = 16 * MB;
-  static const int kRegWxpCompiledLimit = 1 * MB;
+  static const int kRegExpCompiledLimit = 1 * MB;

  private:
   static String* last_ascii_string_;
@@ -1236,6 +1236,12 @@ class BoyerMooreLookahead : public ZoneObject {
   }
   bool EmitSkipInstructions(RegExpMacroAssembler* masm);

+  bool MaxDepthExceeded() {
+    return (++depth_ > kMaxFillInDepth);
+  }
+
+  static const int kMaxFillInDepth = 1024;
+
  private:
// This is the value obtained by EatsAtLeast. If we do not have at least this // many characters left in the sample string then the match is bound to fail.
@@ -1243,6 +1249,7 @@ class BoyerMooreLookahead : public ZoneObject {
   // point.
   int length_;
   RegExpCompiler* compiler_;
+  int depth_;
   // 0x7f for ASCII, 0xffff for UTF-16.
   int max_char_;
   ZoneList<BoyerMoorePositionInfo*>* bitmaps_;
Index: test/mjsunit/regress/regress-126412.js
diff --git a/test/mjsunit/regress/regress-126412.js b/test/mjsunit/regress/regress-126412.js
new file mode 100644
index 0000000000000000000000000000000000000000..91c6b078d8ae15c2157d8d79b730711b6f6f4842
--- /dev/null
+++ b/test/mjsunit/regress/regress-126412.js
@@ -0,0 +1,44 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+function test(string, regexp) {
+  try {
+    string.match(regexp);
+  } catch (e) {
+    if (e instanceof RangeError) {
+ assertEquals("RangeError: Maximum call stack size exceeded", e.toString());
+    }
+  }
+}
+
+test("",  /(A{9999999999}B|C*)*D/);
+test("C", /(A{9999999999}B|C*)*D/);
+test("",  /(A{9999999999}B|C*)*/ );
+test("C",  /(A{9999999999}B|C*)*/ );
+test("",  /(9u|(2\`shj{2147483649,}\r|3|f|y|3*)+8\B)\W93+/);
+test("9u8 ",  /(9u|(2\`shj{2147483649,}\r|3|f|y|3*)+8\B)\W93+/);


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to