Commit dc666202 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Avoid OOM on regexps with nested quantifiers.

http://code.google.com/p/v8/issues/detail?id=1472
Review URL: http://codereview.chromium.org/7170014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8302 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 14bf246d
......@@ -925,6 +925,26 @@ bool RegExpCapture::IsAnchoredAtEnd() {
}
bool RegExpDisjunction::ContainsExpandedQuantifier() {
if (contains_expanded_quantifier_) return true;
int len = alternatives_->length();
for (int i = 0; i < len; i++) {
if (alternatives_->at(i)->ContainsExpandedQuantifier()) return true;
}
return false;
}
bool RegExpAlternative::ContainsExpandedQuantifier() {
if (contains_expanded_quantifier_) return true;
int len = nodes_->length();
for (int i = 0; i < len; i++) {
if (nodes_->at(i)->ContainsExpandedQuantifier()) return true;
}
return false;
}
// Convert regular expression trees to a simple sexp representation.
// This representation should be different from the input grammar
// in as many cases as possible, to make it more difficult for incorrect
......
......@@ -1749,6 +1749,7 @@ class RegExpVisitor BASE_EMBEDDED {
class RegExpTree: public ZoneObject {
public:
static const int kInfinity = kMaxInt;
RegExpTree() : contains_expanded_quantifier_(false) { }
virtual ~RegExpTree() { }
virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
virtual RegExpNode* ToNode(RegExpCompiler* compiler,
......@@ -1758,6 +1759,12 @@ class RegExpTree: public ZoneObject {
virtual bool IsAnchoredAtEnd() { return false; }
virtual int min_match() = 0;
virtual int max_match() = 0;
virtual bool ContainsExpandedQuantifier() {
return contains_expanded_quantifier_;
}
void set_contains_expanded_quantifier(bool value) {
contains_expanded_quantifier_ = value;
}
// Returns the interval of registers used for captures within this
// expression.
virtual Interval CaptureRegisters() { return Interval::Empty(); }
......@@ -1768,6 +1775,9 @@ class RegExpTree: public ZoneObject {
virtual bool Is##Name();
FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE)
#undef MAKE_ASTYPE
protected:
bool contains_expanded_quantifier_;
};
......@@ -1784,6 +1794,7 @@ class RegExpDisjunction: public RegExpTree {
virtual bool IsAnchoredAtEnd();
virtual int min_match() { return min_match_; }
virtual int max_match() { return max_match_; }
virtual bool ContainsExpandedQuantifier();
ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
private:
ZoneList<RegExpTree*>* alternatives_;
......@@ -1805,6 +1816,7 @@ class RegExpAlternative: public RegExpTree {
virtual bool IsAnchoredAtEnd();
virtual int min_match() { return min_match_; }
virtual int max_match() { return max_match_; }
virtual bool ContainsExpandedQuantifier();
ZoneList<RegExpTree*>* nodes() { return nodes_; }
private:
ZoneList<RegExpTree*>* nodes_;
......@@ -1954,7 +1966,8 @@ class RegExpQuantifier: public RegExpTree {
min_(min),
max_(max),
min_match_(min * body->min_match()),
type_(type) {
type_(type),
contains_expanded_quantifier_(false) {
if (max > 0 && body->max_match() > kInfinity / max) {
max_match_ = kInfinity;
} else {
......@@ -1976,6 +1989,9 @@ class RegExpQuantifier: public RegExpTree {
virtual bool IsQuantifier();
virtual int min_match() { return min_match_; }
virtual int max_match() { return max_match_; }
virtual bool ContainsExpandedQuantifier() {
return contains_expanded_quantifier_ || body_->ContainsExpandedQuantifier();
}
int min() { return min_; }
int max() { return max_; }
bool is_possessive() { return type_ == POSSESSIVE; }
......@@ -1990,6 +2006,7 @@ class RegExpQuantifier: public RegExpTree {
int min_match_;
int max_match_;
Type type_;
bool contains_expanded_quantifier_;
};
......@@ -2011,6 +2028,9 @@ class RegExpCapture: public RegExpTree {
virtual bool IsCapture();
virtual int min_match() { return body_->min_match(); }
virtual int max_match() { return body_->max_match(); }
virtual bool ContainsExpandedQuantifier() {
return contains_expanded_quantifier_ || body_->ContainsExpandedQuantifier();
}
RegExpTree* body() { return body_; }
int index() { return index_; }
static int StartRegister(int index) { return index * 2; }
......@@ -2042,6 +2062,9 @@ class RegExpLookahead: public RegExpTree {
virtual bool IsAnchoredAtStart();
virtual int min_match() { return 0; }
virtual int max_match() { return 0; }
virtual bool ContainsExpandedQuantifier() {
return contains_expanded_quantifier_ || body_->ContainsExpandedQuantifier();
}
RegExpTree* body() { return body_; }
bool is_positive() { return is_positive_; }
int capture_count() { return capture_count_; }
......
......@@ -3766,7 +3766,9 @@ RegExpNode* RegExpQuantifier::ToNode(int min,
bool needs_capture_clearing = !capture_registers.is_empty();
if (body_can_be_empty) {
body_start_reg = compiler->AllocateRegister();
} else if (FLAG_regexp_optimization && !needs_capture_clearing) {
} else if (FLAG_regexp_optimization &&
!body->ContainsExpandedQuantifier() &&
!needs_capture_clearing) {
// Only unroll if there are no captures and the body can't be
// empty.
if (min > 0 && min <= kMaxUnrolledMinMatches) {
......@@ -3780,6 +3782,7 @@ RegExpNode* RegExpQuantifier::ToNode(int min,
for (int i = 0; i < min; i++) {
answer = body->ToNode(compiler, answer);
}
if (min > 1) body->set_contains_expanded_quantifier(true);
return answer;
}
if (max <= kMaxUnrolledMaxMatches) {
......@@ -3800,6 +3803,7 @@ RegExpNode* RegExpQuantifier::ToNode(int min,
answer = alternation;
if (not_at_start) alternation->set_not_at_start();
}
if (max > 1) body->set_contains_expanded_quantifier(true);
return answer;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment