Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: src/runtime.cc

Issue 207613005: No longer OOM on invalid string length. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/json-parser.h ('K') | « src/parser.cc ('k') | src/uri.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3326 matching lines...) Expand 10 before | Expand all | Expand 10 after
3337 3337
3338 class ReplacementStringBuilder { 3338 class ReplacementStringBuilder {
3339 public: 3339 public:
3340 ReplacementStringBuilder(Heap* heap, 3340 ReplacementStringBuilder(Heap* heap,
3341 Handle<String> subject, 3341 Handle<String> subject,
3342 int estimated_part_count) 3342 int estimated_part_count)
3343 : heap_(heap), 3343 : heap_(heap),
3344 array_builder_(heap->isolate(), estimated_part_count), 3344 array_builder_(heap->isolate(), estimated_part_count),
3345 subject_(subject), 3345 subject_(subject),
3346 character_count_(0), 3346 character_count_(0),
3347 is_ascii_(subject->IsOneByteRepresentation()), 3347 is_ascii_(subject->IsOneByteRepresentation()) {
3348 overflowed_(false) {
3349 // Require a non-zero initial size. Ensures that doubling the size to 3348 // Require a non-zero initial size. Ensures that doubling the size to
3350 // extend the array will work. 3349 // extend the array will work.
3351 ASSERT(estimated_part_count > 0); 3350 ASSERT(estimated_part_count > 0);
3352 } 3351 }
3353 3352
3354 static inline void AddSubjectSlice(FixedArrayBuilder* builder, 3353 static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3355 int from, 3354 int from,
3356 int to) { 3355 int to) {
3357 ASSERT(from >= 0); 3356 ASSERT(from >= 0);
3358 int length = to - from; 3357 int length = to - from;
(...skipping 27 matching lines...) Expand all
3386 ASSERT(length > 0); 3385 ASSERT(length > 0);
3387 AddElement(*string); 3386 AddElement(*string);
3388 if (!string->IsOneByteRepresentation()) { 3387 if (!string->IsOneByteRepresentation()) {
3389 is_ascii_ = false; 3388 is_ascii_ = false;
3390 } 3389 }
3391 IncrementCharacterCount(length); 3390 IncrementCharacterCount(length);
3392 } 3391 }
3393 3392
3394 3393
3395 Handle<String> ToString() { 3394 Handle<String> ToString() {
3396 if (overflowed_) {
3397 heap_->isolate()->ThrowInvalidStringLength();
3398 return Handle<String>();
3399 }
3400
3401 if (array_builder_.length() == 0) { 3395 if (array_builder_.length() == 0) {
3402 return heap_->isolate()->factory()->empty_string(); 3396 return heap_->isolate()->factory()->empty_string();
3403 } 3397 }
3404 3398
3405 Handle<String> joined_string; 3399 Handle<String> joined_string;
3406 if (is_ascii_) { 3400 if (is_ascii_) {
3407 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); 3401 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3402 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
3408 DisallowHeapAllocation no_gc; 3403 DisallowHeapAllocation no_gc;
3409 uint8_t* char_buffer = seq->GetChars(); 3404 uint8_t* char_buffer = seq->GetChars();
3410 StringBuilderConcatHelper(*subject_, 3405 StringBuilderConcatHelper(*subject_,
3411 char_buffer, 3406 char_buffer,
3412 *array_builder_.array(), 3407 *array_builder_.array(),
3413 array_builder_.length()); 3408 array_builder_.length());
3414 joined_string = Handle<String>::cast(seq); 3409 joined_string = Handle<String>::cast(seq);
3415 } else { 3410 } else {
3416 // Non-ASCII. 3411 // Non-ASCII.
3417 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); 3412 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3413 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
3418 DisallowHeapAllocation no_gc; 3414 DisallowHeapAllocation no_gc;
3419 uc16* char_buffer = seq->GetChars(); 3415 uc16* char_buffer = seq->GetChars();
3420 StringBuilderConcatHelper(*subject_, 3416 StringBuilderConcatHelper(*subject_,
3421 char_buffer, 3417 char_buffer,
3422 *array_builder_.array(), 3418 *array_builder_.array(),
3423 array_builder_.length()); 3419 array_builder_.length());
3424 joined_string = Handle<String>::cast(seq); 3420 joined_string = Handle<String>::cast(seq);
3425 } 3421 }
3426 return joined_string; 3422 return joined_string;
3427 } 3423 }
3428 3424
3429 3425
3430 void IncrementCharacterCount(int by) { 3426 void IncrementCharacterCount(int by) {
3431 if (character_count_ > String::kMaxLength - by) { 3427 if (character_count_ > String::kMaxLength - by) {
3432 overflowed_ = true; 3428 STATIC_ASSERT(String::kMaxLength < kMaxInt);
3429 character_count_ = kMaxInt;
3430 } else {
3431 character_count_ += by;
3433 } 3432 }
3434 character_count_ += by;
3435 } 3433 }
3436 3434
3437 private: 3435 private:
3438 Handle<SeqOneByteString> NewRawOneByteString(int length) { 3436 Handle<SeqOneByteString> NewRawOneByteString(int length) {
3439 return heap_->isolate()->factory()->NewRawOneByteString(length); 3437 return heap_->isolate()->factory()->NewRawOneByteString(length);
3440 } 3438 }
3441 3439
3442 3440
3443 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { 3441 Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3444 return heap_->isolate()->factory()->NewRawTwoByteString(length); 3442 return heap_->isolate()->factory()->NewRawTwoByteString(length);
3445 } 3443 }
3446 3444
3447 3445
3448 void AddElement(Object* element) { 3446 void AddElement(Object* element) {
3449 ASSERT(element->IsSmi() || element->IsString()); 3447 ASSERT(element->IsSmi() || element->IsString());
3450 ASSERT(array_builder_.capacity() > array_builder_.length()); 3448 ASSERT(array_builder_.capacity() > array_builder_.length());
3451 array_builder_.Add(element); 3449 array_builder_.Add(element);
3452 } 3450 }
3453 3451
3454 Heap* heap_; 3452 Heap* heap_;
3455 FixedArrayBuilder array_builder_; 3453 FixedArrayBuilder array_builder_;
3456 Handle<String> subject_; 3454 Handle<String> subject_;
3457 int character_count_; 3455 int character_count_;
3458 bool is_ascii_; 3456 bool is_ascii_;
3459 bool overflowed_;
3460 }; 3457 };
3461 3458
3462 3459
3463 class CompiledReplacement { 3460 class CompiledReplacement {
3464 public: 3461 public:
3465 explicit CompiledReplacement(Zone* zone) 3462 explicit CompiledReplacement(Zone* zone)
3466 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} 3463 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3467 3464
3468 // Return whether the replacement is simple. 3465 // Return whether the replacement is simple.
3469 bool Compile(Handle<String> replacement, 3466 bool Compile(Handle<String> replacement,
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
3906 3903
3907 int matches = indices.length(); 3904 int matches = indices.length();
3908 if (matches == 0) return *subject; 3905 if (matches == 0) return *subject;
3909 3906
3910 // Detect integer overflow. 3907 // Detect integer overflow.
3911 int64_t result_len_64 = 3908 int64_t result_len_64 =
3912 (static_cast<int64_t>(replacement_len) - 3909 (static_cast<int64_t>(replacement_len) -
3913 static_cast<int64_t>(pattern_len)) * 3910 static_cast<int64_t>(pattern_len)) *
3914 static_cast<int64_t>(matches) + 3911 static_cast<int64_t>(matches) +
3915 static_cast<int64_t>(subject_len); 3912 static_cast<int64_t>(subject_len);
3916 if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11); 3913 int result_len;
3917 int result_len = static_cast<int>(result_len_64); 3914 if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
3915 STATIC_ASSERT(String::kMaxLength < kMaxInt);
3916 result_len = kMaxInt; // Provoke exception.
3917 } else {
3918 result_len = static_cast<int>(result_len_64);
3919 }
3918 3920
3919 int subject_pos = 0; 3921 int subject_pos = 0;
3920 int result_pos = 0; 3922 int result_pos = 0;
3921 3923
3922 Handle<ResultSeqString> result; 3924 Handle<ResultSeqString> result;
3923 if (ResultSeqString::kHasAsciiEncoding) { 3925 if (ResultSeqString::kHasAsciiEncoding) {
3924 result = Handle<ResultSeqString>::cast( 3926 result = Handle<ResultSeqString>::cast(
3925 isolate->factory()->NewRawOneByteString(result_len)); 3927 isolate->factory()->NewRawOneByteString(result_len));
3926 } else { 3928 } else {
3927 result = Handle<ResultSeqString>::cast( 3929 result = Handle<ResultSeqString>::cast(
3928 isolate->factory()->NewRawTwoByteString(result_len)); 3930 isolate->factory()->NewRawTwoByteString(result_len));
3929 } 3931 }
3932 RETURN_IF_EMPTY_HANDLE(isolate, result);
3930 3933
3931 for (int i = 0; i < matches; i++) { 3934 for (int i = 0; i < matches; i++) {
3932 // Copy non-matched subject content. 3935 // Copy non-matched subject content.
3933 if (subject_pos < indices.at(i)) { 3936 if (subject_pos < indices.at(i)) {
3934 String::WriteToFlat(*subject, 3937 String::WriteToFlat(*subject,
3935 result->GetChars() + result_pos, 3938 result->GetChars() + result_pos,
3936 subject_pos, 3939 subject_pos,
3937 indices.at(i)); 3940 indices.at(i));
3938 result_pos += indices.at(i) - subject_pos; 3941 result_pos += indices.at(i) - subject_pos;
3939 } 3942 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
4099 if (new_length == 0) return isolate->heap()->empty_string(); 4102 if (new_length == 0) return isolate->heap()->empty_string();
4100 4103
4101 Handle<ResultSeqString> answer; 4104 Handle<ResultSeqString> answer;
4102 if (ResultSeqString::kHasAsciiEncoding) { 4105 if (ResultSeqString::kHasAsciiEncoding) {
4103 answer = Handle<ResultSeqString>::cast( 4106 answer = Handle<ResultSeqString>::cast(
4104 isolate->factory()->NewRawOneByteString(new_length)); 4107 isolate->factory()->NewRawOneByteString(new_length));
4105 } else { 4108 } else {
4106 answer = Handle<ResultSeqString>::cast( 4109 answer = Handle<ResultSeqString>::cast(
4107 isolate->factory()->NewRawTwoByteString(new_length)); 4110 isolate->factory()->NewRawTwoByteString(new_length));
4108 } 4111 }
4109 4112
Igor Sheludko 2014/03/24 13:43:16 ASSERT(!answer.is_null()); ?
4110 int prev = 0; 4113 int prev = 0;
4111 int position = 0; 4114 int position = 0;
4112 4115
4113 do { 4116 do {
4114 start = current_match[0]; 4117 start = current_match[0];
4115 end = current_match[1]; 4118 end = current_match[1];
4116 if (prev < start) { 4119 if (prev < start) {
4117 // Add substring subject[prev;start] to answer string. 4120 // Add substring subject[prev;start] to answer string.
4118 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); 4121 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4119 position += start - prev; 4122 position += start - prev;
(...skipping 2429 matching lines...) Expand 10 before | Expand all | Expand 10 after
6549 6552
6550 // Simpler handling of ASCII strings. 6553 // Simpler handling of ASCII strings.
6551 // 6554 //
6552 // NOTE: This assumes that the upper/lower case of an ASCII 6555 // NOTE: This assumes that the upper/lower case of an ASCII
6553 // character is also ASCII. This is currently the case, but it 6556 // character is also ASCII. This is currently the case, but it
6554 // might break in the future if we implement more context and locale 6557 // might break in the future if we implement more context and locale
6555 // dependent upper/lower conversions. 6558 // dependent upper/lower conversions.
6556 if (s->IsOneByteRepresentationUnderneath()) { 6559 if (s->IsOneByteRepresentationUnderneath()) {
6557 Handle<SeqOneByteString> result = 6560 Handle<SeqOneByteString> result =
6558 isolate->factory()->NewRawOneByteString(length); 6561 isolate->factory()->NewRawOneByteString(length);
6559 6562 ASSERT(!result.is_null()); // Same length as input.
6560 DisallowHeapAllocation no_gc; 6563 DisallowHeapAllocation no_gc;
6561 String::FlatContent flat_content = s->GetFlatContent(); 6564 String::FlatContent flat_content = s->GetFlatContent();
6562 ASSERT(flat_content.IsFlat()); 6565 ASSERT(flat_content.IsFlat());
6563 bool has_changed_character = false; 6566 bool has_changed_character = false;
6564 bool is_ascii = FastAsciiConvert<Converter>( 6567 bool is_ascii = FastAsciiConvert<Converter>(
6565 reinterpret_cast<char*>(result->GetChars()), 6568 reinterpret_cast<char*>(result->GetChars()),
6566 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()), 6569 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
6567 length, 6570 length,
6568 &has_changed_character); 6571 &has_changed_character);
6569 // If not ASCII, we discard the result and take the 2 byte path. 6572 // If not ASCII, we discard the result and take the 2 byte path.
6570 if (is_ascii) return has_changed_character ? *result : *s; 6573 if (is_ascii) return has_changed_character ? *result : *s;
6571 } 6574 }
6572 6575
6573 Handle<SeqString> result; 6576 Handle<SeqString> result;
6574 if (s->IsOneByteRepresentation()) { 6577 if (s->IsOneByteRepresentation()) {
6575 result = isolate->factory()->NewRawOneByteString(length); 6578 result = isolate->factory()->NewRawOneByteString(length);
6576 } else { 6579 } else {
6577 result = isolate->factory()->NewRawTwoByteString(length); 6580 result = isolate->factory()->NewRawTwoByteString(length);
6578 } 6581 }
6582 ASSERT(!result.is_null()); // Same length as input.
6583
6579 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping); 6584 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
6580 Object* answer; 6585 Object* answer;
6581 if (!maybe->ToObject(&answer)) return maybe; 6586 if (!maybe->ToObject(&answer)) return maybe;
6582 if (answer->IsString()) return answer; 6587 if (answer->IsString()) return answer;
6583 6588
6584 ASSERT(answer->IsSmi()); 6589 ASSERT(answer->IsSmi());
6585 length = Smi::cast(answer)->value(); 6590 length = Smi::cast(answer)->value();
6586 if (s->IsOneByteRepresentation() && length > 0) { 6591 if (s->IsOneByteRepresentation() && length > 0) {
6587 result = isolate->factory()->NewRawOneByteString(length); 6592 result = isolate->factory()->NewRawOneByteString(length);
6588 } else { 6593 } else {
6589 if (length < 0) length = -length; 6594 if (length < 0) length = -length;
6590 result = isolate->factory()->NewRawTwoByteString(length); 6595 result = isolate->factory()->NewRawTwoByteString(length);
6591 } 6596 }
6597 RETURN_IF_EMPTY_HANDLE(isolate, result);
6592 return ConvertCaseHelper(isolate, *s, *result, length, mapping); 6598 return ConvertCaseHelper(isolate, *s, *result, length, mapping);
6593 } 6599 }
6594 6600
6595 6601
6596 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { 6602 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6597 return ConvertCase( 6603 return ConvertCase(
6598 args, isolate, isolate->runtime_state()->to_lower_mapping()); 6604 args, isolate, isolate->runtime_state()->to_lower_mapping());
6599 } 6605 }
6600 6606
6601 6607
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
7226 if (max_nof_separators < (array_length - 1)) { 7232 if (max_nof_separators < (array_length - 1)) {
7227 return isolate->ThrowInvalidStringLength(); 7233 return isolate->ThrowInvalidStringLength();
7228 } 7234 }
7229 int length = (array_length - 1) * separator_length; 7235 int length = (array_length - 1) * separator_length;
7230 for (int i = 0; i < array_length; i++) { 7236 for (int i = 0; i < array_length; i++) {
7231 Object* element_obj = fixed_array->get(i); 7237 Object* element_obj = fixed_array->get(i);
7232 RUNTIME_ASSERT(element_obj->IsString()); 7238 RUNTIME_ASSERT(element_obj->IsString());
7233 String* element = String::cast(element_obj); 7239 String* element = String::cast(element_obj);
7234 int increment = element->length(); 7240 int increment = element->length();
7235 if (increment > String::kMaxLength - length) { 7241 if (increment > String::kMaxLength - length) {
7236 return isolate->ThrowInvalidStringLength(); 7242 STATIC_ASSERT(String::kMaxLength < kMaxInt);
7243 length = kMaxInt; // Provoke exception;
7244 break;
7237 } 7245 }
7238 length += increment; 7246 length += increment;
7239 } 7247 }
7240 7248
7241 Handle<SeqTwoByteString> answer = 7249 Handle<SeqTwoByteString> answer =
7242 isolate->factory()->NewRawTwoByteString(length); 7250 isolate->factory()->NewRawTwoByteString(length);
7251 RETURN_IF_EMPTY_HANDLE(isolate, answer);
7243 7252
7244 DisallowHeapAllocation no_gc; 7253 DisallowHeapAllocation no_gc;
7245 7254
7246 uc16* sink = answer->GetChars(); 7255 uc16* sink = answer->GetChars();
7247 #ifdef DEBUG 7256 #ifdef DEBUG
7248 uc16* end = sink + length; 7257 uc16* end = sink + length;
7249 #endif 7258 #endif
7250 7259
7251 String* first = String::cast(fixed_array->get(0)); 7260 String* first = String::cast(fixed_array->get(0));
7252 String* seperator_raw = *separator; 7261 String* seperator_raw = *separator;
(...skipping 2224 matching lines...) Expand 10 before | Expand all | Expand 10 after
9477 "not_date_object", HandleVector<Object>(NULL, 0))); 9486 "not_date_object", HandleVector<Object>(NULL, 0)));
9478 } 9487 }
9479 9488
9480 9489
9481 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) { 9490 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) {
9482 HandleScope scope(isolate); 9491 HandleScope scope(isolate);
9483 ASSERT(args.length() == 1); 9492 ASSERT(args.length() == 1);
9484 CONVERT_SMI_ARG_CHECKED(message_id, 0); 9493 CONVERT_SMI_ARG_CHECKED(message_id, 0);
9485 const char* message = GetBailoutReason( 9494 const char* message = GetBailoutReason(
9486 static_cast<BailoutReason>(message_id)); 9495 static_cast<BailoutReason>(message_id));
9487 Handle<Name> message_handle = 9496 Handle<String> message_handle =
9488 isolate->factory()->NewStringFromAscii(CStrVector(message)); 9497 isolate->factory()->NewStringFromAscii(CStrVector(message));
9498 RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
9489 return isolate->Throw(*message_handle); 9499 return isolate->Throw(*message_handle);
9490 } 9500 }
9491 9501
9492 9502
9493 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { 9503 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9494 SealHandleScope shs(isolate); 9504 SealHandleScope shs(isolate);
9495 ASSERT(args.length() == 0); 9505 ASSERT(args.length() == 0);
9496 9506
9497 // First check if this is a real stack overflow. 9507 // First check if this is a real stack overflow.
9498 if (isolate->stack_guard()->IsStackOverflow()) { 9508 if (isolate->stack_guard()->IsStackOverflow()) {
(...skipping 5541 matching lines...) Expand 10 before | Expand all | Expand 10 after
15040 // Handle last resort GC and make sure to allow future allocations 15050 // Handle last resort GC and make sure to allow future allocations
15041 // to grow the heap without causing GCs (if possible). 15051 // to grow the heap without causing GCs (if possible).
15042 isolate->counters()->gc_last_resort_from_js()->Increment(); 15052 isolate->counters()->gc_last_resort_from_js()->Increment();
15043 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 15053 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
15044 "Runtime::PerformGC"); 15054 "Runtime::PerformGC");
15045 } 15055 }
15046 } 15056 }
15047 15057
15048 15058
15049 } } // namespace v8::internal 15059 } } // namespace v8::internal
OLDNEW
« src/json-parser.h ('K') | « src/parser.cc ('k') | src/uri.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698