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

Side by Side Diff: src/runtime.cc

Issue 521074: Fix potential length-miscalculation in %StringBuilderConcat. (Closed)
Patch Set: Created 10 years, 11 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 1506 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 StringBuilderConcatHelper(*subject_, 1517 StringBuilderConcatHelper(*subject_,
1518 char_buffer, 1518 char_buffer,
1519 *parts_, 1519 *parts_,
1520 part_count_); 1520 part_count_);
1521 } 1521 }
1522 return joined_string; 1522 return joined_string;
1523 } 1523 }
1524 1524
1525 1525
1526 void IncrementCharacterCount(int by) { 1526 void IncrementCharacterCount(int by) {
1527 if (character_count_ > Smi::kMaxValue - by) { 1527 if (character_count_ > String::kMaxLength - by) {
1528 V8::FatalProcessOutOfMemory("String.replace result too large."); 1528 V8::FatalProcessOutOfMemory("String.replace result too large.");
1529 } 1529 }
1530 character_count_ += by; 1530 character_count_ += by;
1531 } 1531 }
1532 1532
1533 private: 1533 private:
1534 1534
1535 Handle<String> NewRawAsciiString(int size) { 1535 Handle<String> NewRawAsciiString(int size) {
1536 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String); 1536 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
1537 } 1537 }
(...skipping 1839 matching lines...) Expand 10 before | Expand all | Expand 10 after
3377 while (buffer->has_more()) { 3377 while (buffer->has_more()) {
3378 uint16_t character = buffer->GetNext(); 3378 uint16_t character = buffer->GetNext();
3379 if (character >= 256) { 3379 if (character >= 256) {
3380 escaped_length += 6; 3380 escaped_length += 6;
3381 } else if (IsNotEscaped(character)) { 3381 } else if (IsNotEscaped(character)) {
3382 escaped_length++; 3382 escaped_length++;
3383 } else { 3383 } else {
3384 escaped_length += 3; 3384 escaped_length += 3;
3385 } 3385 }
3386 // We don't allow strings that are longer than a maximal length. 3386 // We don't allow strings that are longer than a maximal length.
3387 ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
3387 if (escaped_length > String::kMaxLength) { 3388 if (escaped_length > String::kMaxLength) {
3388 Top::context()->mark_out_of_memory(); 3389 Top::context()->mark_out_of_memory();
3389 return Failure::OutOfMemoryException(); 3390 return Failure::OutOfMemoryException();
3390 } 3391 }
3391 } 3392 }
3392 } 3393 }
3393 // No length change implies no change. Return original string if no change. 3394 // No length change implies no change. Return original string if no change.
3394 if (escaped_length == length) { 3395 if (escaped_length == length) {
3395 return source; 3396 return source;
3396 } 3397 }
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
3910 // Position and length encoded in two smis. 3911 // Position and length encoded in two smis.
3911 Object* obj = fixed_array->get(++i); 3912 Object* obj = fixed_array->get(++i);
3912 ASSERT(obj->IsSmi()); 3913 ASSERT(obj->IsSmi());
3913 pos = Smi::cast(obj)->value(); 3914 pos = Smi::cast(obj)->value();
3914 len = -encoded_slice; 3915 len = -encoded_slice;
3915 } 3916 }
3916 String::WriteToFlat(special, 3917 String::WriteToFlat(special,
3917 sink + position, 3918 sink + position,
3918 pos, 3919 pos,
3919 pos + len); 3920 pos + len);
3921 ASSERT(special->length() - position >= len);
3920 position += len; 3922 position += len;
3921 } else { 3923 } else {
3922 String* string = String::cast(element); 3924 String* string = String::cast(element);
3923 int element_length = string->length(); 3925 int element_length = string->length();
3924 String::WriteToFlat(string, sink + position, 0, element_length); 3926 String::WriteToFlat(string, sink + position, 0, element_length);
3927 ASSERT(special->length() - position >= element_length);
3925 position += element_length; 3928 position += element_length;
3926 } 3929 }
3927 } 3930 }
3928 } 3931 }
3929 3932
3930 3933
3931 static Object* Runtime_StringBuilderConcat(Arguments args) { 3934 static Object* Runtime_StringBuilderConcat(Arguments args) {
3932 NoHandleAllocation ha; 3935 NoHandleAllocation ha;
3933 ASSERT(args.length() == 3); 3936 ASSERT(args.length() == 3);
3934 CONVERT_CHECKED(JSArray, array, args[0]); 3937 CONVERT_CHECKED(JSArray, array, args[0]);
(...skipping 18 matching lines...) Expand all
3953 3956
3954 if (array_length == 0) { 3957 if (array_length == 0) {
3955 return Heap::empty_string(); 3958 return Heap::empty_string();
3956 } else if (array_length == 1) { 3959 } else if (array_length == 1) {
3957 Object* first = fixed_array->get(0); 3960 Object* first = fixed_array->get(0);
3958 if (first->IsString()) return first; 3961 if (first->IsString()) return first;
3959 } 3962 }
3960 3963
3961 bool ascii = special->IsAsciiRepresentation(); 3964 bool ascii = special->IsAsciiRepresentation();
3962 int position = 0; 3965 int position = 0;
3966 int increment = 0;
3963 for (int i = 0; i < array_length; i++) { 3967 for (int i = 0; i < array_length; i++) {
3964 Object* elt = fixed_array->get(i); 3968 Object* elt = fixed_array->get(i);
3965 if (elt->IsSmi()) { 3969 if (elt->IsSmi()) {
3966 // Smi encoding of position and length. 3970 // Smi encoding of position and length.
3967 int len = Smi::cast(elt)->value(); 3971 int len = Smi::cast(elt)->value();
3968 if (len > 0) { 3972 if (len > 0) {
3969 // Position and length encoded in one smi. 3973 // Position and length encoded in one smi.
3970 int pos = len >> 11; 3974 int pos = len >> 11;
3971 len &= 0x7ff; 3975 len &= 0x7ff;
3972 if (pos + len > special_length) { 3976 if (pos + len > special_length) {
3973 return Top::Throw(Heap::illegal_argument_symbol()); 3977 return Top::Throw(Heap::illegal_argument_symbol());
3974 } 3978 }
3975 position += len; 3979 increment = len;
3976 } else { 3980 } else {
3977 // Position and length encoded in two smis. 3981 // Position and length encoded in two smis.
3978 position += (-len); 3982 increment = (-len);
3979 // Get the position and check that it is also a smi. 3983 // Get the position and check that it is also a smi.
3980 i++; 3984 i++;
3981 if (i >= array_length) { 3985 if (i >= array_length) {
3982 return Top::Throw(Heap::illegal_argument_symbol()); 3986 return Top::Throw(Heap::illegal_argument_symbol());
3983 } 3987 }
3984 Object* pos = fixed_array->get(i); 3988 Object* pos = fixed_array->get(i);
3985 if (!pos->IsSmi()) { 3989 if (!pos->IsSmi()) {
3986 return Top::Throw(Heap::illegal_argument_symbol()); 3990 return Top::Throw(Heap::illegal_argument_symbol());
3987 } 3991 }
3988 } 3992 }
3989 } else if (elt->IsString()) { 3993 } else if (elt->IsString()) {
3990 String* element = String::cast(elt); 3994 String* element = String::cast(elt);
3991 int element_length = element->length(); 3995 int element_length = element->length();
3992 position += element_length; 3996 increment = element_length;
3993 if (ascii && !element->IsAsciiRepresentation()) { 3997 if (ascii && !element->IsAsciiRepresentation()) {
3994 ascii = false; 3998 ascii = false;
3995 } 3999 }
3996 } else { 4000 } else {
3997 return Top::Throw(Heap::illegal_argument_symbol()); 4001 return Top::Throw(Heap::illegal_argument_symbol());
3998 } 4002 }
3999 if (position > String::kMaxLength) { 4003 if (increment > String::kMaxLength - position) {
4000 Top::context()->mark_out_of_memory(); 4004 Top::context()->mark_out_of_memory();
4001 return Failure::OutOfMemoryException(); 4005 return Failure::OutOfMemoryException();
4002 } 4006 }
4007 position += increment;
4003 } 4008 }
4004 4009
4005 int length = position; 4010 int length = position;
4006 Object* object; 4011 Object* object;
4007 4012
4008 if (ascii) { 4013 if (ascii) {
4009 object = Heap::AllocateRawAsciiString(length); 4014 object = Heap::AllocateRawAsciiString(length);
4010 if (object->IsFailure()) return object; 4015 if (object->IsFailure()) return object;
4011 SeqAsciiString* answer = SeqAsciiString::cast(object); 4016 SeqAsciiString* answer = SeqAsciiString::cast(object);
4012 StringBuilderConcatHelper(special, 4017 StringBuilderConcatHelper(special,
(...skipping 4064 matching lines...) Expand 10 before | Expand all | Expand 10 after
8077 } else { 8082 } else {
8078 // Handle last resort GC and make sure to allow future allocations 8083 // Handle last resort GC and make sure to allow future allocations
8079 // to grow the heap without causing GCs (if possible). 8084 // to grow the heap without causing GCs (if possible).
8080 Counters::gc_last_resort_from_js.Increment(); 8085 Counters::gc_last_resort_from_js.Increment();
8081 Heap::CollectAllGarbage(false); 8086 Heap::CollectAllGarbage(false);
8082 } 8087 }
8083 } 8088 }
8084 8089
8085 8090
8086 } } // namespace v8::internal 8091 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698