Commit e40b33d3 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Correctly check for stack limit in JSON.stringify.

Changes include:
 - inline functions in a way as not to waste stack space.
 - reset StackReserveSize to the value prior to r12808.
 - check stack overflow dynamically.

R=ulan@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12814 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b5598862
...@@ -180,11 +180,6 @@ ...@@ -180,11 +180,6 @@
'defines': [ 'defines': [
'V8_TARGET_ARCH_IA32', 'V8_TARGET_ARCH_IA32',
], ],
'msvs_settings': {
'VCLinkerTool': {
'StackReserveSize': '4194304',
},
},
}], # v8_target_arch=="ia32" }], # v8_target_arch=="ia32"
['v8_target_arch=="mipsel"', { ['v8_target_arch=="mipsel"', {
'defines': [ 'defines': [
...@@ -251,7 +246,7 @@ ...@@ -251,7 +246,7 @@
}, },
'msvs_settings': { 'msvs_settings': {
'VCLinkerTool': { 'VCLinkerTool': {
'StackReserveSize': '8388608', 'StackReserveSize': '2097152',
}, },
}, },
'msvs_configuration_platform': 'x64', 'msvs_configuration_platform': 'x64',
......
...@@ -45,7 +45,6 @@ class BasicJsonStringifier BASE_EMBEDDED { ...@@ -45,7 +45,6 @@ class BasicJsonStringifier BASE_EMBEDDED {
static const int kInitialPartLength = 32; static const int kInitialPartLength = 32;
static const int kMaxPartLength = 16 * 1024; static const int kMaxPartLength = 16 * 1024;
static const int kPartLengthGrowthFactor = 2; static const int kPartLengthGrowthFactor = 2;
static const int kStackLimit = 4 * 1024;
enum Result { UNCHANGED, SUCCESS, BAILOUT, CIRCULAR, STACK_OVERFLOW }; enum Result { UNCHANGED, SUCCESS, BAILOUT, CIRCULAR, STACK_OVERFLOW };
...@@ -77,10 +76,10 @@ class BasicJsonStringifier BASE_EMBEDDED { ...@@ -77,10 +76,10 @@ class BasicJsonStringifier BASE_EMBEDDED {
} }
} }
INLINE(Handle<Object> GetProperty(Handle<JSObject> object, Handle<Object> GetProperty(Handle<JSObject> object,
Handle<String> key)); Handle<String> key);
INLINE(bool MayHaveToJsonFunction(Handle<JSObject> object)); bool MayHaveToJsonFunction(Handle<JSObject> object);
INLINE(Result Serialize(Handle<Object> object)) { INLINE(Result Serialize(Handle<Object> object)) {
return Serialize_<false>(object); return Serialize_<false>(object);
...@@ -98,22 +97,21 @@ class BasicJsonStringifier BASE_EMBEDDED { ...@@ -98,22 +97,21 @@ class BasicJsonStringifier BASE_EMBEDDED {
bool comma = false, bool comma = false,
Handle<String> key = Handle<String>::null()); Handle<String> key = Handle<String>::null());
INLINE(void SerializeDeferredKey(bool deferred_comma, void SerializeDeferredKey(bool deferred_comma, Handle<String> deferred_key) {
Handle<String> deferred_key)) {
if (deferred_comma) Append(','); if (deferred_comma) Append(',');
SerializeString(deferred_key); SerializeString(deferred_key);
Append(':'); Append(':');
} }
INLINE(Result SerializeSmi(Smi* object)); Result SerializeSmi(Smi* object);
INLINE(Result SerializeDouble(double number)); Result SerializeDouble(double number);
INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) {
return SerializeDouble(object->value()); return SerializeDouble(object->value());
} }
Result SerializeArray(Handle<JSArray> object); INLINE(Result SerializeArray(Handle<JSArray> object));
Result SerializeObject(Handle<JSObject> object); INLINE(Result SerializeObject(Handle<JSObject> object));
void SerializeString(Handle<String> object); void SerializeString(Handle<String> object);
...@@ -132,8 +130,8 @@ class BasicJsonStringifier BASE_EMBEDDED { ...@@ -132,8 +130,8 @@ class BasicJsonStringifier BASE_EMBEDDED {
template <typename Char> template <typename Char>
INLINE(Vector<const Char> GetCharVector(Handle<String> string)); INLINE(Vector<const Char> GetCharVector(Handle<String> string));
INLINE(Result StackPush(Handle<Object> object)); Result StackPush(Handle<Object> object);
INLINE(void StackPop()); void StackPop();
INLINE(Handle<String> accumulator()) { INLINE(Handle<String> accumulator()) {
return Handle<String>(String::cast(accumulator_store_->value())); return Handle<String>(String::cast(accumulator_store_->value()));
...@@ -298,8 +296,10 @@ bool BasicJsonStringifier::MayHaveToJsonFunction(Handle<JSObject> object) { ...@@ -298,8 +296,10 @@ bool BasicJsonStringifier::MayHaveToJsonFunction(Handle<JSObject> object) {
BasicJsonStringifier::Result BasicJsonStringifier::StackPush( BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
Handle<Object> object) { Handle<Object> object) {
StackLimitCheck check(isolate_);
if (check.HasOverflowed()) return STACK_OVERFLOW;
int length = Smi::cast(stack_->length())->value(); int length = Smi::cast(stack_->length())->value();
if (length > kStackLimit) return STACK_OVERFLOW;
FixedArray* elements = FixedArray::cast(stack_->elements()); FixedArray* elements = FixedArray::cast(stack_->elements());
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
if (elements->get(i) == *object) { if (elements->get(i) == *object) {
...@@ -473,9 +473,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject( ...@@ -473,9 +473,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject(
GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw); GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
if (threw) return BAILOUT; if (threw) return BAILOUT;
Append('{'); Append('{');
int length = contents->length();
bool comma = false; bool comma = false;
for (int i = 0; i < length; i++) { for (int i = 0; i < contents->length(); i++) {
Object* key = contents->get(i); Object* key = contents->get(i);
Handle<String> key_handle; Handle<String> key_handle;
Handle<Object> property; Handle<Object> property;
......
...@@ -42,15 +42,17 @@ assertThrows(function() { rec(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4) }, ...@@ -42,15 +42,17 @@ assertThrows(function() { rec(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4) },
RangeError); RangeError);
var depth1 = 2048;
var depth2 = 10000;
var deepArray = []; var deepArray = [];
for (var i = 0; i < 2048; i++) deepArray = [deepArray]; for (var i = 0; i < depth1; i++) deepArray = [deepArray];
JSON.stringify(deepArray); JSON.stringify(deepArray);
for (var i = 2048; i < 4097; i++) deepArray = [deepArray]; for (var i = depth1; i < depth2; i++) deepArray = [deepArray];
assertThrows(function() { JSON.stringify(deepArray); }, RangeError); assertThrows(function() { JSON.stringify(deepArray); }, RangeError);
var deepObject = {}; var deepObject = {};
for (var i = 0; i < 2048; i++) deepObject = { next: deepObject }; for (var i = 0; i < depth1; i++) deepObject = { next: deepObject };
JSON.stringify(deepObject); JSON.stringify(deepObject);
for (var i = 2048; i < 4097; i++) deepObject = { next: deepObject }; for (var i = depth1; i < depth2; i++) deepObject = { next: deepObject };
assertThrows(function() { JSON.stringify(deepObject); }, RangeError); assertThrows(function() { JSON.stringify(deepObject); }, RangeError);
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