Revision: 11710
Author: [email protected]
Date: Tue Jun 5 01:06:18 2012
Log: Backport to 3.10 of r11696: Limit work done analyzing regexps
with very large fanout.
BUG=128821
Original review URL: https://chromiumcodereview.appspot.com/10448117
Review URL: https://chromiumcodereview.appspot.com/10536002
http://code.google.com/p/v8/source/detail?r=11710
Modified:
/branches/3.10/src/jsregexp.cc
/branches/3.10/src/jsregexp.h
/branches/3.10/src/version.cc
/branches/3.10/test/mjsunit/regexp-capture-3.js
/branches/3.10/test/mjsunit/regexp-capture.js
=======================================
--- /branches/3.10/src/jsregexp.cc Thu May 31 06:54:25 2012
+++ /branches/3.10/src/jsregexp.cc Tue Jun 5 01:06:18 2012
@@ -2175,12 +2175,14 @@
void ActionNode::FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
if (type_ == BEGIN_SUBMATCH) {
bm->SetRest(offset);
} else if (type_ != POSITIVE_SUBMATCH_SUCCESS) {
- on_success()->FillInBMInfo(offset, recursion_depth + 1, bm,
not_at_start);
+ on_success()->FillInBMInfo(
+ offset, recursion_depth + 1, budget - 1, bm, not_at_start);
}
SaveBMInfo(bm, not_at_start, offset);
}
@@ -2204,11 +2206,13 @@
void AssertionNode::FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
// Match the behaviour of EatsAtLeast on this node.
if (type() == AT_START && not_at_start) return;
- on_success()->FillInBMInfo(offset, recursion_depth + 1, bm,
not_at_start);
+ on_success()->FillInBMInfo(
+ offset, recursion_depth + 1, budget - 1, bm, not_at_start);
SaveBMInfo(bm, not_at_start, offset);
}
@@ -2791,15 +2795,18 @@
void LoopChoiceNode::FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
if (body_can_be_zero_length_ ||
- recursion_depth > RegExpCompiler::kMaxRecursion) {
+ recursion_depth > RegExpCompiler::kMaxRecursion ||
+ budget <= 0) {
bm->SetRest(offset);
SaveBMInfo(bm, not_at_start, offset);
return;
}
- ChoiceNode::FillInBMInfo(offset, recursion_depth + 1, bm, not_at_start);
+ ChoiceNode::FillInBMInfo(
+ offset, recursion_depth + 1, budget - 1, bm, not_at_start);
SaveBMInfo(bm, not_at_start, offset);
}
@@ -2901,7 +2908,7 @@
if (eats_at_least >= 1) {
BoyerMooreLookahead* bm =
new BoyerMooreLookahead(eats_at_least, compiler);
- FillInBMInfo(0, 0, bm, not_at_start);
+ FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start);
if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE;
if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE;
}
@@ -3839,7 +3846,7 @@
BoyerMooreLookahead* bm =
new BoyerMooreLookahead(eats_at_least, compiler);
GuardedAlternative alt0 = alternatives_->at(0);
- alt0.node()->FillInBMInfo(0, 0, bm, not_at_start);
+ alt0.node()->FillInBMInfo(0, 0, kFillInBMBudget, bm,
not_at_start);
skip_was_emitted = bm->EmitSkipInstructions(macro_assembler);
}
} else {
@@ -5580,6 +5587,7 @@
void BackReferenceNode::FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
// Working out the set of characters that a backreference can match is
too
@@ -5595,9 +5603,11 @@
void ChoiceNode::FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
ZoneList<GuardedAlternative>* alts = alternatives();
+ budget = (budget - 1) / alts->length();
for (int i = 0; i < alts->length(); i++) {
GuardedAlternative& alt = alts->at(i);
if (alt.guards() != NULL && alt.guards()->length() != 0) {
@@ -5605,7 +5615,8 @@
SaveBMInfo(bm, not_at_start, offset);
return;
}
- alt.node()->FillInBMInfo(offset, recursion_depth + 1, bm,
not_at_start);
+ alt.node()->FillInBMInfo(
+ offset, recursion_depth + 1, budget, bm, not_at_start);
}
SaveBMInfo(bm, not_at_start, offset);
}
@@ -5613,6 +5624,7 @@
void TextNode::FillInBMInfo(int initial_offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
if (initial_offset >= bm->length()) return;
@@ -5669,6 +5681,7 @@
}
on_success()->FillInBMInfo(offset,
recursion_depth + 1,
+ budget - 1,
bm,
true); // Not at start after a text node.
if (initial_offset == 0) set_bm_info(not_at_start, bm);
=======================================
--- /branches/3.10/src/jsregexp.h Thu May 31 06:54:25 2012
+++ /branches/3.10/src/jsregexp.h Tue Jun 5 01:06:18 2012
@@ -574,9 +574,12 @@
// Collects information on the possible code units (mod 128) that can
match if
// we look forward. This is used for a Boyer-Moore-like string searching
// implementation. TODO(erikcorry): This should share more code with
- // EatsAtLeast, GetQuickCheckDetails.
+ // EatsAtLeast, GetQuickCheckDetails. The budget argument is used to
limit
+ // the number of nodes we are willing to look at in order to create this
data.
+ static const int kFillInBMBudget = 200;
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
UNREACHABLE();
@@ -679,9 +682,11 @@
virtual RegExpNode* FilterASCII(int depth);
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
- on_success_->FillInBMInfo(offset, recursion_depth + 1, bm,
not_at_start);
+ on_success_->FillInBMInfo(
+ offset, recursion_depth + 1, budget - 1, bm, not_at_start);
if (offset == 0) set_bm_info(not_at_start, bm);
}
@@ -736,6 +741,7 @@
}
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
Type type() { return type_; }
@@ -807,6 +813,7 @@
RegExpCompiler* compiler);
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
void CalculateOffsets();
@@ -869,6 +876,7 @@
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
AssertionNodeType type() { return type_; }
@@ -909,6 +917,7 @@
}
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
@@ -936,6 +945,7 @@
}
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
// Returning 0 from EatsAtLeast should ensure we never get here.
@@ -1028,6 +1038,7 @@
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
@@ -1080,10 +1091,11 @@
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
alternatives_->at(1).node()->FillInBMInfo(
- offset, recursion_depth + 1, bm, not_at_start);
+ offset, recursion_depth + 1, budget - 1, bm, not_at_start);
if (offset == 0) set_bm_info(not_at_start, bm);
}
// For a negative lookahead we don't emit the quick check for the
@@ -1115,6 +1127,7 @@
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
+ int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
RegExpNode* loop_node() { return loop_node_; }
=======================================
--- /branches/3.10/src/version.cc Thu May 31 06:54:25 2012
+++ /branches/3.10/src/version.cc Tue Jun 5 01:06:18 2012
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 10
#define BUILD_NUMBER 8
-#define PATCH_LEVEL 12
+#define PATCH_LEVEL 13
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.10/test/mjsunit/regexp-capture-3.js Thu May 31 06:54:25 2012
+++ /branches/3.10/test/mjsunit/regexp-capture-3.js Tue Jun 5 01:06:18 2012
@@ -162,7 +162,6 @@
// string we can test that the relevant node is removed by verifying that
// there is no hang.
function NoHang(re) {
- print(re);
"This is an ASCII string that could take forever".match(re);
}
=======================================
--- /branches/3.10/test/mjsunit/regexp-capture.js Mon Apr 18 08:51:38 2011
+++ /branches/3.10/test/mjsunit/regexp-capture.js Tue Jun 5 01:06:18 2012
@@ -56,3 +56,5 @@
assertEquals(["bbaa", "a", "", "a"],
/((\3|b)\2(a)){2,}/.exec("bbaababbabaaaaabbaaaabba"));
+// From crbug.com/128821 - don't hang:
+"".match(/((a|i|A|I|u|o|U|O)(s|c|b|c|d|f|g|h|j|k|l|m|n|p|q|r|s|t|v|w|x|y|z|
B|C|D|F|G|H|J|K|L|M|N|P|Q|R|S|T|V|W|X|Y|Z)*) de\/da([.,!?\s]|$)/);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev