Throw exception on invalid string length instead of OOM.
R=bmeurer@chromium.org BUG=349329 LOG=Y Review URL: https://codereview.chromium.org/199853004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20112 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
bfcc117f4c
commit
9ba80269ee
@ -5475,6 +5475,8 @@ Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
|
||||
i::Handle<i::String> right_string = Utils::OpenHandle(*right);
|
||||
i::Handle<i::String> result = isolate->factory()->NewConsString(left_string,
|
||||
right_string);
|
||||
// We do not expect this to throw an exception. Change this if it does.
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate, result);
|
||||
return Utils::ToLocal(result);
|
||||
}
|
||||
|
||||
@ -6966,9 +6968,12 @@ Handle<String> CpuProfileNode::GetFunctionName() const {
|
||||
return ToApiHandle<String>(
|
||||
isolate->factory()->InternalizeUtf8String(entry->name()));
|
||||
} else {
|
||||
return ToApiHandle<String>(isolate->factory()->NewConsString(
|
||||
i::Handle<i::String> cons = isolate->factory()->NewConsString(
|
||||
isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
|
||||
isolate->factory()->InternalizeUtf8String(entry->name())));
|
||||
isolate->factory()->InternalizeUtf8String(entry->name()));
|
||||
// We do not expect this to throw an exception. Change this if it does.
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate, cons);
|
||||
return ToApiHandle<String>(cons);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,9 +377,7 @@ Handle<String> Factory::NewConsString(Handle<String> left,
|
||||
// Make sure that an out of memory exception is thrown if the length
|
||||
// of the new cons string is too large.
|
||||
if (length > String::kMaxLength || length < 0) {
|
||||
isolate()->context()->mark_out_of_memory();
|
||||
V8::FatalProcessOutOfMemory("String concatenation result too large.");
|
||||
UNREACHABLE();
|
||||
isolate()->ThrowInvalidStringLength();
|
||||
return Handle<String>::null();
|
||||
}
|
||||
|
||||
|
@ -83,11 +83,14 @@ Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
|
||||
return MakeNameFromStackHelper(pos + 1, prev);
|
||||
} else {
|
||||
if (prev->length() > 0) {
|
||||
Handle<String> name = names_stack_.at(pos).name;
|
||||
if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
|
||||
Factory* factory = isolate()->factory();
|
||||
Handle<String> curr = factory->NewConsString(
|
||||
factory->dot_string(), names_stack_.at(pos).name);
|
||||
return MakeNameFromStackHelper(pos + 1,
|
||||
factory->NewConsString(prev, curr));
|
||||
Handle<String> curr = factory->NewConsString(factory->dot_string(), name);
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate(), curr);
|
||||
curr = factory->NewConsString(prev, curr);
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate(), curr);
|
||||
return MakeNameFromStackHelper(pos + 1, curr);
|
||||
} else {
|
||||
return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
|
||||
}
|
||||
|
@ -951,6 +951,12 @@ Failure* Isolate::ThrowIllegalOperation() {
|
||||
}
|
||||
|
||||
|
||||
Failure* Isolate::ThrowInvalidStringLength() {
|
||||
return Throw(*factory()->NewRangeError(
|
||||
"invalid_string_length", HandleVector<Object>(NULL, 0)));
|
||||
}
|
||||
|
||||
|
||||
void Isolate::ScheduleThrow(Object* exception) {
|
||||
// When scheduling a throw we first throw the exception to get the
|
||||
// error reporting if it is uncaught before rescheduling it.
|
||||
|
@ -789,6 +789,7 @@ class Isolate {
|
||||
// Return pending location if any or unfilled structure.
|
||||
MessageLocation GetMessageLocation();
|
||||
Failure* ThrowIllegalOperation();
|
||||
Failure* ThrowInvalidStringLength();
|
||||
|
||||
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
|
||||
Failure* PromoteScheduledException();
|
||||
|
@ -51,6 +51,8 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
||||
|
||||
enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW };
|
||||
|
||||
void Accumulate();
|
||||
|
||||
void Extend();
|
||||
|
||||
void ChangeEncoding();
|
||||
@ -178,6 +180,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
||||
int current_index_;
|
||||
int part_length_;
|
||||
bool is_ascii_;
|
||||
bool overflowed_;
|
||||
|
||||
static const int kJsonEscapeTableEntrySize = 8;
|
||||
static const char* const JsonEscapeTable;
|
||||
@ -254,7 +257,10 @@ const char* const BasicJsonStringifier::JsonEscapeTable =
|
||||
|
||||
|
||||
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
|
||||
: isolate_(isolate), current_index_(0), is_ascii_(true) {
|
||||
: isolate_(isolate),
|
||||
current_index_(0),
|
||||
is_ascii_(true),
|
||||
overflowed_(false) {
|
||||
factory_ = isolate_->factory();
|
||||
accumulator_store_ = Handle<JSValue>::cast(
|
||||
factory_->ToObject(factory_->empty_string()));
|
||||
@ -269,9 +275,12 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
|
||||
switch (SerializeObject(object)) {
|
||||
case UNCHANGED:
|
||||
return isolate_->heap()->undefined_value();
|
||||
case SUCCESS:
|
||||
case SUCCESS: {
|
||||
ShrinkCurrentPart();
|
||||
return *factory_->NewConsString(accumulator(), current_part_);
|
||||
Accumulate();
|
||||
if (overflowed_) return isolate_->ThrowInvalidStringLength();
|
||||
return *accumulator();
|
||||
}
|
||||
case CIRCULAR:
|
||||
return isolate_->Throw(*factory_->NewTypeError(
|
||||
"circular_structure", HandleVector<Object>(NULL, 0)));
|
||||
@ -486,7 +495,9 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric(
|
||||
part_length_ = kInitialPartLength; // Allocate conservatively.
|
||||
Extend(); // Attach current part and allocate new part.
|
||||
// Attach result string to the accumulator.
|
||||
set_accumulator(factory_->NewConsString(accumulator(), result_string));
|
||||
Handle<String> cons = factory_->NewConsString(accumulator(), result_string);
|
||||
RETURN_IF_EMPTY_HANDLE_VALUE(isolate_, cons, EXCEPTION);
|
||||
set_accumulator(cons);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -708,8 +719,20 @@ void BasicJsonStringifier::ShrinkCurrentPart() {
|
||||
}
|
||||
|
||||
|
||||
void BasicJsonStringifier::Accumulate() {
|
||||
if (accumulator()->length() + current_part_->length() > String::kMaxLength) {
|
||||
// Screw it. Simply set the flag and carry on. Throw exception at the end.
|
||||
// We most likely will trigger a real OOM before even reaching this point.
|
||||
set_accumulator(factory_->empty_string());
|
||||
overflowed_ = true;
|
||||
} else {
|
||||
set_accumulator(factory_->NewConsString(accumulator(), current_part_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BasicJsonStringifier::Extend() {
|
||||
set_accumulator(factory_->NewConsString(accumulator(), current_part_));
|
||||
Accumulate();
|
||||
if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
|
||||
part_length_ *= kPartLengthGrowthFactor;
|
||||
}
|
||||
@ -724,7 +747,7 @@ void BasicJsonStringifier::Extend() {
|
||||
|
||||
void BasicJsonStringifier::ChangeEncoding() {
|
||||
ShrinkCurrentPart();
|
||||
set_accumulator(factory_->NewConsString(accumulator(), current_part_));
|
||||
Accumulate();
|
||||
current_part_ = factory_->NewRawTwoByteString(part_length_);
|
||||
current_index_ = 0;
|
||||
is_ascii_ = false;
|
||||
|
@ -2922,6 +2922,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
||||
Factory* heap_factory = isolate()->factory();
|
||||
Handle<String> tempstr =
|
||||
heap_factory->NewConsString(heap_factory->dot_for_string(), name);
|
||||
RETURN_IF_EMPTY_HANDLE_VALUE(isolate(), tempstr, 0);
|
||||
Handle<String> tempname = heap_factory->InternalizeString(tempstr);
|
||||
Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
|
||||
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
||||
|
@ -3330,7 +3330,8 @@ class ReplacementStringBuilder {
|
||||
array_builder_(heap->isolate(), estimated_part_count),
|
||||
subject_(subject),
|
||||
character_count_(0),
|
||||
is_ascii_(subject->IsOneByteRepresentation()) {
|
||||
is_ascii_(subject->IsOneByteRepresentation()),
|
||||
overflowed_(false) {
|
||||
// Require a non-zero initial size. Ensures that doubling the size to
|
||||
// extend the array will work.
|
||||
ASSERT(estimated_part_count > 0);
|
||||
@ -3378,6 +3379,11 @@ class ReplacementStringBuilder {
|
||||
|
||||
|
||||
Handle<String> ToString() {
|
||||
if (overflowed_) {
|
||||
heap_->isolate()->ThrowInvalidStringLength();
|
||||
return Handle<String>();
|
||||
}
|
||||
|
||||
if (array_builder_.length() == 0) {
|
||||
return heap_->isolate()->factory()->empty_string();
|
||||
}
|
||||
@ -3409,7 +3415,7 @@ class ReplacementStringBuilder {
|
||||
|
||||
void IncrementCharacterCount(int by) {
|
||||
if (character_count_ > String::kMaxLength - by) {
|
||||
V8::FatalProcessOutOfMemory("String.replace result too large.");
|
||||
overflowed_ = true;
|
||||
}
|
||||
character_count_ += by;
|
||||
}
|
||||
@ -3436,6 +3442,7 @@ class ReplacementStringBuilder {
|
||||
Handle<String> subject_;
|
||||
int character_count_;
|
||||
bool is_ascii_;
|
||||
bool overflowed_;
|
||||
};
|
||||
|
||||
|
||||
@ -4034,7 +4041,9 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
|
||||
capture_count,
|
||||
global_cache.LastSuccessfulMatch());
|
||||
|
||||
return *(builder.ToString());
|
||||
Handle<String> result = builder.ToString();
|
||||
RETURN_IF_EMPTY_HANDLE(isolate, result);
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
@ -4180,8 +4189,8 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
|
||||
replace,
|
||||
found,
|
||||
recursion_limit - 1);
|
||||
if (*found) return isolate->factory()->NewConsString(new_first, second);
|
||||
if (new_first.is_null()) return new_first;
|
||||
if (*found) return isolate->factory()->NewConsString(new_first, second);
|
||||
|
||||
Handle<String> new_second =
|
||||
StringReplaceOneCharWithString(isolate,
|
||||
@ -4190,8 +4199,8 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
|
||||
replace,
|
||||
found,
|
||||
recursion_limit - 1);
|
||||
if (*found) return isolate->factory()->NewConsString(first, new_second);
|
||||
if (new_second.is_null()) return new_second;
|
||||
if (*found) return isolate->factory()->NewConsString(first, new_second);
|
||||
|
||||
return subject;
|
||||
} else {
|
||||
@ -4200,6 +4209,7 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
|
||||
*found = true;
|
||||
Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
|
||||
Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
|
||||
RETURN_IF_EMPTY_HANDLE_VALUE(isolate, cons1, Handle<String>());
|
||||
Handle<String> second =
|
||||
isolate->factory()->NewSubString(subject, index + 1, subject->length());
|
||||
return isolate->factory()->NewConsString(cons1, second);
|
||||
@ -4225,6 +4235,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
|
||||
&found,
|
||||
kRecursionLimit);
|
||||
if (!result.is_null()) return *result;
|
||||
if (isolate->has_pending_exception()) return Failure::Exception();
|
||||
return *StringReplaceOneCharWithString(isolate,
|
||||
FlattenGetString(subject),
|
||||
search,
|
||||
@ -6225,7 +6236,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
|
||||
Handle<String> result = string->IsOneByteRepresentationUnderneath()
|
||||
? URIEscape::Escape<uint8_t>(isolate, source)
|
||||
: URIEscape::Escape<uc16>(isolate, source);
|
||||
if (result.is_null()) return Failure::OutOfMemoryException(0x12);
|
||||
RETURN_IF_EMPTY_HANDLE(isolate, result);
|
||||
return *result;
|
||||
}
|
||||
|
||||
@ -6359,9 +6370,9 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
|
||||
int char_length = mapping->get(current, 0, chars);
|
||||
if (char_length == 0) char_length = 1;
|
||||
current_length += char_length;
|
||||
if (current_length > Smi::kMaxValue) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
return Failure::OutOfMemoryException(0x13);
|
||||
if (current_length > String::kMaxLength) {
|
||||
AllowHeapAllocation allocate_error_and_return;
|
||||
return isolate->ThrowInvalidStringLength();
|
||||
}
|
||||
}
|
||||
// Try again with the real length. Return signed if we need
|
||||
@ -7016,7 +7027,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
|
||||
isolate->counters()->string_add_runtime()->Increment();
|
||||
return *isolate->factory()->NewConsString(str1, str2);
|
||||
Handle<String> result = isolate->factory()->NewConsString(str1, str2);
|
||||
RETURN_IF_EMPTY_HANDLE(isolate, result);
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
@ -7063,10 +7076,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
|
||||
if (!args[1]->IsSmi()) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
return Failure::OutOfMemoryException(0x14);
|
||||
}
|
||||
if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
|
||||
int array_length = args.smi_at(1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
|
||||
|
||||
@ -7140,8 +7150,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
if (increment > String::kMaxLength - position) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
return Failure::OutOfMemoryException(0x15);
|
||||
return isolate->ThrowInvalidStringLength();
|
||||
}
|
||||
position += increment;
|
||||
}
|
||||
@ -7176,20 +7185,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
SealHandleScope shs(isolate);
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 3);
|
||||
CONVERT_ARG_CHECKED(JSArray, array, 0);
|
||||
if (!args[1]->IsSmi()) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
return Failure::OutOfMemoryException(0x16);
|
||||
}
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
|
||||
if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
|
||||
int array_length = args.smi_at(1);
|
||||
CONVERT_ARG_CHECKED(String, separator, 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
|
||||
RUNTIME_ASSERT(array->HasFastObjectElements());
|
||||
|
||||
if (!array->HasFastObjectElements()) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
FixedArray* fixed_array = FixedArray::cast(array->elements());
|
||||
Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
|
||||
if (fixed_array->length() < array_length) {
|
||||
array_length = fixed_array->length();
|
||||
}
|
||||
@ -7198,38 +7202,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
return isolate->heap()->empty_string();
|
||||
} else if (array_length == 1) {
|
||||
Object* first = fixed_array->get(0);
|
||||
if (first->IsString()) return first;
|
||||
RUNTIME_ASSERT(first->IsString());
|
||||
return first;
|
||||
}
|
||||
|
||||
int separator_length = separator->length();
|
||||
int max_nof_separators =
|
||||
(String::kMaxLength + separator_length - 1) / separator_length;
|
||||
if (max_nof_separators < (array_length - 1)) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
return Failure::OutOfMemoryException(0x17);
|
||||
return isolate->ThrowInvalidStringLength();
|
||||
}
|
||||
int length = (array_length - 1) * separator_length;
|
||||
for (int i = 0; i < array_length; i++) {
|
||||
Object* element_obj = fixed_array->get(i);
|
||||
if (!element_obj->IsString()) {
|
||||
// TODO(1161): handle this case.
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
RUNTIME_ASSERT(element_obj->IsString());
|
||||
String* element = String::cast(element_obj);
|
||||
int increment = element->length();
|
||||
if (increment > String::kMaxLength - length) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
return Failure::OutOfMemoryException(0x18);
|
||||
return isolate->ThrowInvalidStringLength();
|
||||
}
|
||||
length += increment;
|
||||
}
|
||||
|
||||
Object* object;
|
||||
{ MaybeObject* maybe_object =
|
||||
isolate->heap()->AllocateRawTwoByteString(length);
|
||||
if (!maybe_object->ToObject(&object)) return maybe_object;
|
||||
}
|
||||
SeqTwoByteString* answer = SeqTwoByteString::cast(object);
|
||||
Handle<SeqTwoByteString> answer =
|
||||
isolate->factory()->NewRawTwoByteString(length);
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
uc16* sink = answer->GetChars();
|
||||
#ifdef DEBUG
|
||||
@ -7237,13 +7235,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
#endif
|
||||
|
||||
String* first = String::cast(fixed_array->get(0));
|
||||
String* seperator_raw = *separator;
|
||||
int first_length = first->length();
|
||||
String::WriteToFlat(first, sink, 0, first_length);
|
||||
sink += first_length;
|
||||
|
||||
for (int i = 1; i < array_length; i++) {
|
||||
ASSERT(sink + separator_length <= end);
|
||||
String::WriteToFlat(separator, sink, 0, separator_length);
|
||||
String::WriteToFlat(seperator_raw, sink, 0, separator_length);
|
||||
sink += separator_length;
|
||||
|
||||
String* element = String::cast(fixed_array->get(i));
|
||||
@ -7256,7 +7255,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
|
||||
// Use %_FastAsciiArrayJoin instead.
|
||||
ASSERT(!answer->IsOneByteRepresentation());
|
||||
return answer;
|
||||
return *answer;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
@ -7357,9 +7356,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
|
||||
// Throw an exception if the resulting string is too large. See
|
||||
// https://code.google.com/p/chromium/issues/detail?id=336820
|
||||
// for details.
|
||||
return isolate->Throw(*isolate->factory()->
|
||||
NewRangeError("invalid_string_length",
|
||||
HandleVector<Object>(NULL, 0)));
|
||||
return isolate->ThrowInvalidStringLength();
|
||||
}
|
||||
|
||||
if (is_ascii) {
|
||||
|
@ -264,7 +264,8 @@ Handle<String> URIEscape::Escape(Isolate* isolate, Handle<String> string) {
|
||||
// We don't allow strings that are longer than a maximal length.
|
||||
ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
|
||||
if (escaped_length > String::kMaxLength) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
AllowHeapAllocation allocate_error_and_return;
|
||||
isolate->ThrowInvalidStringLength();
|
||||
return Handle<String>::null();
|
||||
}
|
||||
}
|
||||
|
@ -1209,24 +1209,17 @@ TEST(AsciiArrayJoin) {
|
||||
// starting with 'bad', followed by 2^14 times the string s. That means the
|
||||
// total length of the concatenated strings is 2^31 + 3. So on 32bit systems
|
||||
// summing the lengths of the strings (as Smis) overflows and wraps.
|
||||
static const char* join_causing_out_of_memory =
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
v8::TryCatch try_catch;
|
||||
CHECK(CompileRun(
|
||||
"var two_14 = Math.pow(2, 14);"
|
||||
"var two_17 = Math.pow(2, 17);"
|
||||
"var s = Array(two_17 + 1).join('c');"
|
||||
"var a = ['bad'];"
|
||||
"for (var i = 1; i <= two_14; i++) a.push(s);"
|
||||
"a.join("");";
|
||||
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
LocalContext context;
|
||||
v8::V8::IgnoreOutOfMemoryException();
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(
|
||||
v8::String::NewFromUtf8(CcTest::isolate(), join_causing_out_of_memory));
|
||||
v8::Local<v8::Value> result = script->Run();
|
||||
|
||||
// Check for out of memory state.
|
||||
CHECK(result.IsEmpty());
|
||||
CHECK(context->HasOutOfMemoryException());
|
||||
"a.join("");").IsEmpty());
|
||||
CHECK(try_catch.HasCaught());
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
# When that bug is fixed, revert the expectation to:
|
||||
# Skip long running test in debug and allow it to timeout in release mode.
|
||||
# regress/regress-524: [PASS, TIMEOUT, ['mode == debug', SKIP]],
|
||||
'string-oom-slow-*': [SLOW, ['mode == debug', SKIP]],
|
||||
|
||||
# This test non-deterministically runs out of memory on Windows ia32.
|
||||
'regress/regress-crbug-160010': [SKIP],
|
||||
|
14
test/mjsunit/string-oom-array-join.js
Normal file
14
test/mjsunit/string-oom-array-join.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var a = "a";
|
||||
for (var i = 0; i < 23; i++) a += a;
|
||||
var b = [];
|
||||
for (var i = 0; i < (1<<5); i++) b.push(a);
|
||||
|
||||
function join() {
|
||||
b.join();
|
||||
}
|
||||
|
||||
assertThrows(join, RangeError);
|
12
test/mjsunit/string-oom-concat.js
Normal file
12
test/mjsunit/string-oom-concat.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
function concat() {
|
||||
var a = " ";
|
||||
for (var i = 0; i < 100; i++) {
|
||||
a += a;
|
||||
}
|
||||
}
|
||||
|
||||
assertThrows(concat, RangeError);
|
14
test/mjsunit/string-oom-replace-global-regexp-with-string.js
Normal file
14
test/mjsunit/string-oom-replace-global-regexp-with-string.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var a = 'a';
|
||||
for (var i = 0; i < 5; i++) a += a;
|
||||
var b = 'b';
|
||||
for (var i = 0; i < 23; i++) b += b;
|
||||
|
||||
function replace() {
|
||||
a.replace(/./g, b);
|
||||
}
|
||||
|
||||
assertThrows(replace, RangeError);
|
@ -0,0 +1,14 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var a = "a";
|
||||
for (var i = 0; i < 5; i++) a += a;
|
||||
var b = "b";
|
||||
for (var i = 0; i < 23; i++) b += b;
|
||||
|
||||
function replace() {
|
||||
a.replace(/a/g, function() { return b });
|
||||
}
|
||||
|
||||
assertThrows(replace, RangeError);
|
14
test/mjsunit/string-oom-slow-escape.js
Normal file
14
test/mjsunit/string-oom-slow-escape.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
|
||||
var a = '<';
|
||||
for (var i = 0; i < 26; i++) a += a;
|
||||
a = a + a + a;
|
||||
|
||||
function escape_a() {
|
||||
escape(a);
|
||||
}
|
||||
|
||||
assertThrows(escape_a, RangeError);
|
13
test/mjsunit/string-oom-slow-json-stringify.js
Normal file
13
test/mjsunit/string-oom-slow-json-stringify.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var a = 'a';
|
||||
for (var i = 0; i < 20; i++) a += a;
|
||||
for (var i = 0; i < 8; i++) a = [a, a];
|
||||
|
||||
function stringify() {
|
||||
JSON.stringify(a);
|
||||
}
|
||||
|
||||
assertThrows(stringify, RangeError);
|
12
test/mjsunit/string-oom-slow-replace-one-with-string.js
Normal file
12
test/mjsunit/string-oom-slow-replace-one-with-string.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var a = 'a';
|
||||
for (var i = 0; i < 27; i++) a += a;
|
||||
|
||||
function replace() {
|
||||
a.replace('a', a);
|
||||
}
|
||||
|
||||
assertThrows(replace, RangeError);
|
12
test/mjsunit/string-oom-slow-to-uppercase.js
Normal file
12
test/mjsunit/string-oom-slow-to-uppercase.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var s = "\u00df"; // ß
|
||||
for (var i = 0; i < 27; i++) s += s;
|
||||
|
||||
function upper() {
|
||||
s.toUpperCase();
|
||||
}
|
||||
|
||||
assertThrows(upper, RangeError);
|
Loading…
Reference in New Issue
Block a user