Catch stack overflow in JSON.parse.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 25 Oct 2012 12:36:40 +0000 (12:36 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 25 Oct 2012 12:36:40 +0000 (12:36 +0000)
BUG=

Review URL: https://chromiumcodereview.appspot.com/11275039

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12816 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/json-parser.h
test/mjsunit/json-recursive.js

index 9aa4201..d481ed0 100644 (file)
@@ -195,8 +195,10 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source,
   AdvanceSkipWhitespace();
   Handle<Object> result = ParseJsonValue();
   if (result.is_null() || c0_ != kEndOfString) {
-    // Parse failed. Current character is the unexpected token.
+    // Some exception (for example stack overflow) is already pending.
+    if (isolate_->has_pending_exception()) return Handle<Object>::null();
 
+    // Parse failed. Current character is the unexpected token.
     const char* message;
     Factory* factory = this->factory();
     Handle<JSArray> array;
@@ -247,6 +249,12 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source,
 // Parse any JSON value.
 template <bool seq_ascii>
 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
+  StackLimitCheck stack_check(isolate_);
+  if (stack_check.HasOverflowed()) {
+    isolate_->StackOverflow();
+    return Handle<Object>::null();
+  }
+
   if (c0_ == '"') return ParseJsonString();
   if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
   if (c0_ == '{') return ParseJsonObject();
index adfd93b..0ecca2b 100644 (file)
@@ -56,3 +56,11 @@ for (var i = 0; i < depth1; i++) deepObject = { next: deepObject };
 JSON.stringify(deepObject);
 for (var i = depth1; i < depth2; i++) deepObject = { next: deepObject };
 assertThrows(function() { JSON.stringify(deepObject); }, RangeError);
+
+
+var str = "[1]";
+for (var i = 0; i < 100000; i++) {
+  str = "[1," + str + "]";
+}
+
+assertThrows(function() { JSON.parse(str); }, RangeError);