if (length == -1) length = StringLength(data);
i::Handle<i::String> result = NewString(
isolate->factory(), type, i::Vector<const Char>(data, length));
+ // We do not expect this to fail. Change this if it does.
+ CHECK(!result.is_null());
if (type == String::kUndetectableString) {
result->MarkAsUndetectable();
}
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);
+ // We do not expect this to fail. Change this if it does.
+ CHECK(!result.is_null());
return Utils::ToLocal(result);
}
static i::Handle<i::String> NewExternalStringHandle(
i::Isolate* isolate,
v8::String::ExternalStringResource* resource) {
- return isolate->factory()->NewExternalStringFromTwoByte(resource);
+ i::Handle<i::String> result =
+ isolate->factory()->NewExternalStringFromTwoByte(resource);
+ // We do not expect this to fail. Change this if it does.
+ CHECK(!result.is_null());
+ return result;
}
static i::Handle<i::String> NewExternalAsciiStringHandle(
i::Isolate* isolate,
v8::String::ExternalAsciiStringResource* resource) {
- return isolate->factory()->NewExternalStringFromAscii(resource);
+ i::Handle<i::String> result =
+ isolate->factory()->NewExternalStringFromAscii(resource);
+ // We do not expect this to fail. Change this if it does.
+ CHECK(!result.is_null());
+ return result;
}
i::Handle<i::String> cons = isolate->factory()->NewConsString(
isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
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);
+ // We do not expect this to fail. Change this if it does.
+ CHECK(!cons.is_null());
return ToApiHandle<String>(cons);
}
}
source.length());
Handle<String> source_code =
isolate_->factory()->NewExternalStringFromAscii(resource);
+ // We do not expect this to throw an exception. Change this if it does.
+ CHECK_NOT_EMPTY_HANDLE(isolate_, source_code);
heap->natives_source_cache()->set(index, *source_code);
}
Handle<Object> cached_source(heap->natives_source_cache()->get(index),
Handle<String> source_code =
factory->NewStringFromAscii(
ExperimentalNatives::GetRawScriptSource(index));
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, source_code, false);
return CompileNative(isolate, name, source_code);
}
if (cache == NULL || !cache->Lookup(name, &function_info)) {
ASSERT(source->IsOneByteRepresentation());
Handle<String> script_name = factory->NewStringFromUtf8(name);
+ ASSERT(!script_name.is_null());
function_info = Compiler::CompileScript(
source,
script_name,
ASSERT_EQ(".prototype", period_pos);
Vector<const char> property(holder_expr,
static_cast<int>(period_pos - holder_expr));
+ Handle<String> property_string = factory->InternalizeUtf8String(property);
+ ASSERT(!property_string.is_null());
Handle<JSFunction> function = Handle<JSFunction>::cast(
- GetProperty(isolate, global, factory->InternalizeUtf8String(property)));
+ GetProperty(isolate, global, property_string));
return Handle<JSObject>(JSObject::cast(function->prototype()));
}
}
Handle<String> source_code =
isolate->factory()->NewExternalStringFromAscii(extension->source());
+ // We do not expect this to throw an exception. Change this if it does.
+ CHECK_NOT_EMPTY_HANDLE(isolate, source_code);
bool result = CompileScriptCached(isolate,
CStrVector(extension->name()),
source_code,
cache_->CopyTo(0, *new_array, 0, cache_->length());
cache_ = *new_array;
Handle<String> str = factory->NewStringFromAscii(name, TENURED);
+ ASSERT(!str.is_null());
cache_->set(length, *str);
cache_->set(length + 1, *shared);
Script::cast(shared->script())->set_type(Smi::FromInt(type_));
Handle<Object> result(error_message_for_code_gen_from_strings(),
GetIsolate());
if (!result->IsUndefined()) return result;
- return GetIsolate()->factory()->NewStringFromAscii(i::CStrVector(
+ return GetIsolate()->factory()->NewStringFromOneByte(STATIC_ASCII_VECTOR(
"Code generation from strings disallowed for this context"));
}
isolate->bootstrapper()->NativesSourceLookup(index);
Vector<const char> name = Natives::GetScriptName(index);
Handle<String> script_name = factory->NewStringFromAscii(name);
+ ASSERT(!script_name.is_null());
Handle<Context> context = isolate->native_context();
// Compile the script.
// Create the execution state object.
Handle<String> constructor_str =
isolate_->factory()->InternalizeUtf8String(constructor_name);
+ ASSERT(!constructor_str.is_null());
Handle<Object> constructor(
isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
isolate_);
Handle<SeqOneByteString> Factory::NewRawOneByteString(int length,
- PretenureFlag pretenure) {
+ PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateRawOneByteString(length, pretenure),
ASSERT(left->IsFlat());
ASSERT(right->IsFlat());
+ STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
if (is_one_byte) {
Handle<SeqOneByteString> result = NewRawOneByteString(length);
DisallowHeapAllocation no_gc;
if (!FLAG_string_slices || length < SlicedString::kMinLength) {
if (str->IsOneByteRepresentation()) {
Handle<SeqOneByteString> result = NewRawOneByteString(length);
+ ASSERT(!result.is_null());
uint8_t* dest = result->GetChars();
DisallowHeapAllocation no_gc;
String::WriteToFlat(*str, dest, begin, end);
return result;
} else {
Handle<SeqTwoByteString> result = NewRawTwoByteString(length);
+ ASSERT(!result.is_null());
uc16* dest = result->GetChars();
DisallowHeapAllocation no_gc;
String::WriteToFlat(*str, dest, begin, end);
MaybeObject* Heap::AllocateOneByteInternalizedString(Vector<const uint8_t> str,
uint32_t hash_field) {
if (str.length() > String::kMaxLength) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ return isolate()->ThrowInvalidStringLength();
}
// Compute map and object size.
Map* map = ascii_internalized_string_map();
MaybeObject* Heap::AllocateTwoByteInternalizedString(Vector<const uc16> str,
uint32_t hash_field) {
if (str.length() > String::kMaxLength) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ return isolate()->ThrowInvalidStringLength();
}
// Compute map and object size.
Map* map = internalized_string_map();
const ExternalAsciiString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ return isolate()->ThrowInvalidStringLength();
}
Map* map = external_ascii_string_map();
const ExternalTwoByteString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ return isolate()->ThrowInvalidStringLength();
}
// For small strings we check whether the resource contains only
int size;
Map* map;
- if (chars > String::kMaxLength) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ if (chars < 0 || chars > String::kMaxLength) {
+ return isolate()->ThrowInvalidStringLength();
}
if (is_one_byte) {
map = ascii_internalized_string_map();
MaybeObject* Heap::AllocateRawOneByteString(int length,
PretenureFlag pretenure) {
if (length < 0 || length > String::kMaxLength) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ return isolate()->ThrowInvalidStringLength();
}
int size = SeqOneByteString::SizeFor(length);
ASSERT(size <= SeqOneByteString::kMaxSize);
MaybeObject* Heap::AllocateRawTwoByteString(int length,
PretenureFlag pretenure) {
if (length < 0 || length > String::kMaxLength) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ return isolate()->ThrowInvalidStringLength();
}
int size = SeqTwoByteString::SizeFor(length);
ASSERT(size <= SeqTwoByteString::kMaxSize);
HConstant* c_right = HConstant::cast(right);
HConstant* c_left = HConstant::cast(left);
if (c_left->HasStringValue() && c_right->HasStringValue()) {
- Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString(
- c_left->StringValue(), c_right->StringValue());
- return HConstant::New(zone, context, concat);
+ Handle<String> left_string = c_left->StringValue();
+ Handle<String> right_string = c_right->StringValue();
+ // Prevent possible exception by invalid string length.
+ if (left_string->length() + right_string->length() < String::kMaxLength) {
+ Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString(
+ c_left->StringValue(), c_right->StringValue());
+ ASSERT(!concat.is_null());
+ return HConstant::New(zone, context, concat);
+ }
}
}
return new(zone) HStringAdd(
int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
Handle<StringType> seq_string =
NewRawString<StringType>(factory(), length, pretenure_);
+ ASSERT(!seq_string.is_null());
// Copy prefix into seq_str.
SinkChar* dest = seq_string->GetChars();
String::WriteToFlat(*prefix, dest, start, end);
} while (c0_ != '"');
int length = position_ - beg_pos;
Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
+ ASSERT(!result.is_null());
uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
String::WriteToFlat(*source_, dest, beg_pos, position_);
factory_->ToObject(factory_->empty_string()));
part_length_ = kInitialPartLength;
current_part_ = factory_->NewRawOneByteString(part_length_);
+ ASSERT(!current_part_.is_null());
tojson_string_ = factory_->toJSON_string();
stack_ = factory_->NewJSArray(8);
}
if (object->IsOneByteRepresentationUnderneath()) {
Handle<String> result =
isolate->factory()->NewRawOneByteString(worst_case_length);
+ ASSERT(!result.is_null());
DisallowHeapAllocation no_gc;
return StringifyString_<SeqOneByteString>(
isolate,
} else {
Handle<String> result =
isolate->factory()->NewRawTwoByteString(worst_case_length);
+ ASSERT(!result.is_null());
DisallowHeapAllocation no_gc;
return StringifyString_<SeqTwoByteString>(
isolate,
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 {
} else {
current_part_ = factory_->NewRawTwoByteString(part_length_);
}
+ ASSERT(!current_part_.is_null());
current_index_ = 0;
}
ShrinkCurrentPart();
Accumulate();
current_part_ = factory_->NewRawTwoByteString(part_length_);
+ ASSERT(!current_part_.is_null());
current_index_ = 0;
is_ascii_ = false;
}
// Unable to compile regexp.
Handle<String> error_message =
isolate->factory()->NewStringFromUtf8(CStrVector(result.error_message));
+ ASSERT(!error_message.is_null());
CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate);
return false;
}
DropActivationsInActiveThread(shared_info_array, result, do_drop);
if (error_message != NULL) {
// Add error message as an array extra element.
- Vector<const char> vector_message(error_message, StrLength(error_message));
- Handle<String> str = isolate->factory()->NewStringFromAscii(vector_message);
+ Handle<String> str = isolate->factory()->NewStringFromAscii(
+ CStrVector(error_message));
SetElementSloppy(result, len, str);
}
return result;
Handle<String> result = symbol_cache_.at(symbol_id);
if (result.is_null()) {
result = scanner()->AllocateInternalizedString(isolate_);
+ ASSERT(!result.is_null());
symbol_cache_.at(symbol_id) = result;
return result;
}
Handle<FixedArray> elements = factory->NewFixedArray(args.length());
for (int i = 0; i < args.length(); i++) {
Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
+ ASSERT(!arg_string.is_null());
elements->set(i, *arg_string);
}
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
parser_->scanner()->LogSymbol(parser_->log_, parser_->position());
}
}
- return parser_->scanner()->AllocateInternalizedString(parser_->isolate_);
+ Handle<String> result =
+ parser_->scanner()->AllocateInternalizedString(parser_->isolate_);
+ ASSERT(!result.is_null());
+ return result;
}
return;
}
Handle<String> message_string =
- isolate()->factory()->NewStringFromUtf8(CStrVector("Variable"),
- TENURED);
+ isolate()->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("Variable"));
Expression* expression =
NewThrowTypeError(isolate()->factory()->redeclaration_string(),
message_string, name);
RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
failed_ = true;
*error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
+ ASSERT(!error_->is_null());
// Zip to the end to make sure the no more input is read.
current_ = kEndMarker;
next_pos_ = in()->length();
array_builder_(heap->isolate(), estimated_part_count),
subject_(subject),
character_count_(0),
- is_ascii_(subject->IsOneByteRepresentation()),
- overflowed_(false) {
+ is_ascii_(subject->IsOneByteRepresentation()) {
// Require a non-zero initial size. Ensures that doubling the size to
// extend the array will work.
ASSERT(estimated_part_count > 0);
Handle<String> ToString() {
- if (overflowed_) {
- heap_->isolate()->ThrowInvalidStringLength();
- return Handle<String>();
- }
-
if (array_builder_.length() == 0) {
return heap_->isolate()->factory()->empty_string();
}
Handle<String> joined_string;
if (is_ascii_) {
Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
+ RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
DisallowHeapAllocation no_gc;
uint8_t* char_buffer = seq->GetChars();
StringBuilderConcatHelper(*subject_,
} else {
// Non-ASCII.
Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
+ RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
DisallowHeapAllocation no_gc;
uc16* char_buffer = seq->GetChars();
StringBuilderConcatHelper(*subject_,
void IncrementCharacterCount(int by) {
if (character_count_ > String::kMaxLength - by) {
- overflowed_ = true;
+ STATIC_ASSERT(String::kMaxLength < kMaxInt);
+ character_count_ = kMaxInt;
+ } else {
+ character_count_ += by;
}
- character_count_ += by;
}
private:
Handle<String> subject_;
int character_count_;
bool is_ascii_;
- bool overflowed_;
};
static_cast<int64_t>(pattern_len)) *
static_cast<int64_t>(matches) +
static_cast<int64_t>(subject_len);
- if (result_len_64 > INT_MAX) {
- v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+ int result_len;
+ if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
+ STATIC_ASSERT(String::kMaxLength < kMaxInt);
+ result_len = kMaxInt; // Provoke exception.
+ } else {
+ result_len = static_cast<int>(result_len_64);
}
- int result_len = static_cast<int>(result_len_64);
int subject_pos = 0;
int result_pos = 0;
- Handle<ResultSeqString> result;
+ Handle<String> result_seq;
if (ResultSeqString::kHasAsciiEncoding) {
- result = Handle<ResultSeqString>::cast(
- isolate->factory()->NewRawOneByteString(result_len));
+ result_seq = isolate->factory()->NewRawOneByteString(result_len);
} else {
- result = Handle<ResultSeqString>::cast(
- isolate->factory()->NewRawTwoByteString(result_len));
+ result_seq = isolate->factory()->NewRawTwoByteString(result_len);
}
+ RETURN_IF_EMPTY_HANDLE(isolate, result_seq);
+ Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(result_seq);
for (int i = 0; i < matches; i++) {
// Copy non-matched subject content.
answer = Handle<ResultSeqString>::cast(
isolate->factory()->NewRawTwoByteString(new_length));
}
+ ASSERT(!answer.is_null());
int prev = 0;
int position = 0;
if (s->IsOneByteRepresentationUnderneath()) {
Handle<SeqOneByteString> result =
isolate->factory()->NewRawOneByteString(length);
-
+ ASSERT(!result.is_null()); // Same length as input.
DisallowHeapAllocation no_gc;
String::FlatContent flat_content = s->GetFlatContent();
ASSERT(flat_content.IsFlat());
} else {
result = isolate->factory()->NewRawTwoByteString(length);
}
+ ASSERT(!result.is_null()); // Same length as input.
+
MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
Object* answer;
if (!maybe->ToObject(&answer)) return maybe;
if (length < 0) length = -length;
result = isolate->factory()->NewRawTwoByteString(length);
}
+ RETURN_IF_EMPTY_HANDLE(isolate, result);
return ConvertCaseHelper(isolate, *s, *result, length, mapping);
}
String* element = String::cast(element_obj);
int increment = element->length();
if (increment > String::kMaxLength - length) {
- return isolate->ThrowInvalidStringLength();
+ STATIC_ASSERT(String::kMaxLength < kMaxInt);
+ length = kMaxInt; // Provoke exception;
+ break;
}
length += increment;
}
Handle<SeqTwoByteString> answer =
isolate->factory()->NewRawTwoByteString(length);
+ RETURN_IF_EMPTY_HANDLE(isolate, answer);
DisallowHeapAllocation no_gc;
CONVERT_SMI_ARG_CHECKED(message_id, 0);
const char* message = GetBailoutReason(
static_cast<BailoutReason>(message_id));
- Handle<Name> message_handle =
+ Handle<String> message_handle =
isolate->factory()->NewStringFromAscii(CStrVector(message));
+ RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
return isolate->Throw(*message_handle);
}
int dest_position = 0;
Handle<String> second_part;
+ ASSERT(unescaped_length <= String::kMaxLength);
if (one_byte) {
Handle<SeqOneByteString> dest =
isolate->factory()->NewRawOneByteString(unescaped_length);
+ ASSERT(!dest.is_null());
DisallowHeapAllocation no_allocation;
Vector<const Char> vector = GetCharVector<Char>(string);
for (int i = start_index; i < length; dest_position++) {
} else {
Handle<SeqTwoByteString> dest =
isolate->factory()->NewRawTwoByteString(unescaped_length);
+ ASSERT(!dest.is_null());
DisallowHeapAllocation no_allocation;
Vector<const Char> vector = GetCharVector<Char>(string);
for (int i = start_index; i < length; dest_position++) {
// We don't allow strings that are longer than a maximal length.
ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
- if (escaped_length > String::kMaxLength) {
- AllowHeapAllocation allocate_error_and_return;
- isolate->ThrowInvalidStringLength();
- return Handle<String>::null();
- }
+ if (escaped_length > String::kMaxLength) break; // Provoke exception.
}
}
Handle<SeqOneByteString> dest =
isolate->factory()->NewRawOneByteString(escaped_length);
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, dest, Handle<String>());
int dest_position = 0;
{ DisallowHeapAllocation no_allocation;
'test-api/Threading2': [PASS, ['mode == debug', SLOW]],
'test-api/Threading3': [PASS, ['mode == debug', SLOW]],
'test-api/Threading4': [PASS, ['mode == debug', SLOW]],
+ 'test-strings/StringOOM*': [PASS, ['mode == debug', SKIP]],
}], # ALWAYS
##############################################################################
CHECK_EQ(Min(upper, lower), test);
}
}
+
+
+class DummyResource: public v8::String::ExternalStringResource {
+ public:
+ virtual const uint16_t* data() const { return NULL; }
+ virtual size_t length() const { return 1 << 30; }
+};
+
+
+class DummyOneByteResource: public v8::String::ExternalOneByteStringResource {
+ public:
+ virtual const char* data() const { return NULL; }
+ virtual size_t length() const { return 1 << 30; }
+};
+
+
+TEST(InvalidExternalString) {
+ CcTest::InitializeVM();
+ LocalContext context;
+ Isolate* isolate = CcTest::i_isolate();
+ { HandleScope scope(isolate);
+ DummyOneByteResource r;
+ CHECK(isolate->factory()->NewExternalStringFromAscii(&r).is_null());
+ CHECK(isolate->has_pending_exception());
+ isolate->clear_pending_exception();
+ }
+
+ { HandleScope scope(isolate);
+ DummyResource r;
+ CHECK(isolate->factory()->NewExternalStringFromTwoByte(&r).is_null());
+ CHECK(isolate->has_pending_exception());
+ isolate->clear_pending_exception();
+ }
+}
+
+
+#define INVALID_STRING_TEST(FUN, TYPE) \
+ TEST(StringOOM##FUN) { \
+ CcTest::InitializeVM(); \
+ LocalContext context; \
+ Isolate* isolate = CcTest::i_isolate(); \
+ STATIC_ASSERT(String::kMaxLength < kMaxInt); \
+ static const int invalid = String::kMaxLength + 1; \
+ HandleScope scope(isolate); \
+ Vector<TYPE> dummy = Vector<TYPE>::New(invalid); \
+ CHECK(isolate->factory()->FUN(Vector<const TYPE>::cast(dummy)).is_null()); \
+ memset(dummy.start(), 0x20, dummy.length() * sizeof(TYPE)); \
+ CHECK(isolate->has_pending_exception()); \
+ isolate->clear_pending_exception(); \
+ dummy.Dispose(); \
+ }
+
+INVALID_STRING_TEST(NewStringFromAscii, char)
+INVALID_STRING_TEST(NewStringFromUtf8, char)
+INVALID_STRING_TEST(NewStringFromOneByte, uint8_t)
+INVALID_STRING_TEST(InternalizeOneByteString, uint8_t)
+INVALID_STRING_TEST(InternalizeUtf8String, char)
+
+#undef INVALID_STRING_TEST
// 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() {
+function replace1() {
a.replace(/./g, b);
}
-assertThrows(replace, RangeError);
+assertThrows(replace1, RangeError);
+
+
+var a = 'a';
+for (var i = 0; i < 16; i++) a += a;
+
+function replace2() {
+ a.replace(/a/g, a);
+}
+
+assertThrows(replace2, RangeError);
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(source_),
length / 2));
+ CHECK_NOT_EMPTY_HANDLE(isolate, result);
stream_ =
new GenericStringUtf16CharacterStream(result, 0, result->length());
break;
case LATIN1: {
Handle<String> result = isolate->factory()->NewStringFromOneByte(
Vector<const uint8_t>(source_, length));
+ CHECK_NOT_EMPTY_HANDLE(isolate, result);
stream_ =
new GenericStringUtf16CharacterStream(result, 0, result->length());
break;