Author: [email protected]
Date: Wed May 27 04:23:26 2009
New Revision: 2064
Modified:
branches/bleeding_edge/src/jsregexp.cc
branches/bleeding_edge/src/jsregexp.h
branches/bleeding_edge/test/mjsunit/regexp.js
Log:
Added stack overflow check for RegExp analysis phase.
A very long regexp graph can overflow the stack with recursive calls.
Review URL: http://codereview.chromium.org/113894
Modified: branches/bleeding_edge/src/jsregexp.cc
==============================================================================
--- branches/bleeding_edge/src/jsregexp.cc (original)
+++ branches/bleeding_edge/src/jsregexp.cc Wed May 27 04:23:26 2009
@@ -4189,6 +4189,11 @@
void Analysis::EnsureAnalyzed(RegExpNode* that) {
+ StackLimitCheck check;
+ if (check.HasOverflowed()) {
+ fail("Stack overflow");
+ return;
+ }
if (that->info()->been_analyzed || that->info()->being_analyzed)
return;
that->info()->being_analyzed = true;
@@ -4226,16 +4231,20 @@
that->MakeCaseIndependent();
}
EnsureAnalyzed(that->on_success());
- that->CalculateOffsets();
+ if (!has_failed()) {
+ that->CalculateOffsets();
+ }
}
void Analysis::VisitAction(ActionNode* that) {
RegExpNode* target = that->on_success();
EnsureAnalyzed(target);
- // If the next node is interested in what it follows then this node
- // has to be interested too so it can pass the information on.
- that->info()->AddFromFollowing(target->info());
+ if (!has_failed()) {
+ // If the next node is interested in what it follows then this node
+ // has to be interested too so it can pass the information on.
+ that->info()->AddFromFollowing(target->info());
+ }
}
@@ -4244,6 +4253,7 @@
for (int i = 0; i < that->alternatives()->length(); i++) {
RegExpNode* node = that->alternatives()->at(i).node();
EnsureAnalyzed(node);
+ if (has_failed()) return;
// Anything the following nodes need to know has to be known by
// this node also, so it can pass it on.
info->AddFromFollowing(node->info());
@@ -4257,13 +4267,16 @@
RegExpNode* node = that->alternatives()->at(i).node();
if (node != that->loop_node()) {
EnsureAnalyzed(node);
+ if (has_failed()) return;
info->AddFromFollowing(node->info());
}
}
// Check the loop last since it may need the value of this node
// to get a correct result.
EnsureAnalyzed(that->loop_node());
- info->AddFromFollowing(that->loop_node()->info());
+ if (!has_failed()) {
+ info->AddFromFollowing(that->loop_node()->info());
+ }
}
@@ -4435,6 +4448,10 @@
data->node = node;
Analysis analysis(ignore_case);
analysis.EnsureAnalyzed(node);
+ if (analysis.has_failed()) {
+ const char* error_message = analysis.error_message();
+ return CompilationResult(error_message);
+ }
NodeInfo info = *node->info();
Modified: branches/bleeding_edge/src/jsregexp.h
==============================================================================
--- branches/bleeding_edge/src/jsregexp.h (original)
+++ branches/bleeding_edge/src/jsregexp.h Wed May 27 04:23:26 2009
@@ -1310,7 +1310,7 @@
class Analysis: public NodeVisitor {
public:
explicit Analysis(bool ignore_case)
- : ignore_case_(ignore_case) { }
+ : ignore_case_(ignore_case), error_message_(NULL) { }
void EnsureAnalyzed(RegExpNode* node);
#define DECLARE_VISIT(Type) \
@@ -1319,8 +1319,17 @@
#undef DECLARE_VISIT
virtual void VisitLoopChoice(LoopChoiceNode* that);
+ bool has_failed() { return error_message_ != NULL; }
+ const char* error_message() {
+ ASSERT(error_message_ != NULL);
+ return error_message_;
+ }
+ void fail(const char* error_message) {
+ error_message_ = error_message;
+ }
private:
bool ignore_case_;
+ const char* error_message_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
};
Modified: branches/bleeding_edge/test/mjsunit/regexp.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/regexp.js (original)
+++ branches/bleeding_edge/test/mjsunit/regexp.js Wed May 27 04:23:26 2009
@@ -375,3 +375,16 @@
// Don't hang on this one.
/[^\xfe-\xff]*/.test("");
+
+
+var long = "a";
+for (var i = 0; i < 100000; i++) {
+ long = "a?" + long;
+}
+// Don't crash on this one, but maybe throw an exception.
+try {
+ RegExp(long).exec("a");
+} catch (e) {
+ assertTrue(String(e).indexOf("Stack overflow") >= 0, "overflow");
+}
+
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---