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

Side by Side Diff: src/heap.cc

Issue 525064: Fixed potential length miscalculations by limiting max size of arrays and strings. (Closed)
Patch Set: Added (unrelated) cast to make Win64 compile. 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 | src/objects.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 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 if (Heap::InNewSpace(target)) { 797 if (Heap::InNewSpace(target)) {
798 // String is still in new space. Update the table entry. 798 // String is still in new space. Update the table entry.
799 *last = target; 799 *last = target;
800 ++last; 800 ++last;
801 } else { 801 } else {
802 // String got promoted. Move it to the old string list. 802 // String got promoted. Move it to the old string list.
803 ExternalStringTable::AddOldString(target); 803 ExternalStringTable::AddOldString(target);
804 } 804 }
805 } 805 }
806 806
807 ExternalStringTable::ShrinkNewStrings(last - start); 807 ASSERT(last <= end);
808 ExternalStringTable::ShrinkNewStrings(static_cast<int>(last - start));
808 } 809 }
809 810
810 811
811 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, 812 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
812 Address new_space_front) { 813 Address new_space_front) {
813 do { 814 do {
814 ASSERT(new_space_front <= new_space_.top()); 815 ASSERT(new_space_front <= new_space_.top());
815 816
816 // The addresses new_space_front and new_space_.top() define a 817 // The addresses new_space_front and new_space_.top() define a
817 // queue of unprocessed copied objects. Process them until the 818 // queue of unprocessed copied objects. Process them until the
(...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 2012
2012 Object* result = Heap::AllocateRawTwoByteString(1); 2013 Object* result = Heap::AllocateRawTwoByteString(1);
2013 if (result->IsFailure()) return result; 2014 if (result->IsFailure()) return result;
2014 String* answer = String::cast(result); 2015 String* answer = String::cast(result);
2015 answer->Set(0, code); 2016 answer->Set(0, code);
2016 return answer; 2017 return answer;
2017 } 2018 }
2018 2019
2019 2020
2020 Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { 2021 Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
2022 if (length < 0 || length > ByteArray::kMaxLength) {
2023 return Failure::OutOfMemoryException();
2024 }
2021 if (pretenure == NOT_TENURED) { 2025 if (pretenure == NOT_TENURED) {
2022 return AllocateByteArray(length); 2026 return AllocateByteArray(length);
2023 } 2027 }
2024 int size = ByteArray::SizeFor(length); 2028 int size = ByteArray::SizeFor(length);
2025 Object* result = (size <= MaxObjectSizeInPagedSpace()) 2029 Object* result = (size <= MaxObjectSizeInPagedSpace())
2026 ? old_data_space_->AllocateRaw(size) 2030 ? old_data_space_->AllocateRaw(size)
2027 : lo_space_->AllocateRaw(size); 2031 : lo_space_->AllocateRaw(size);
2028 if (result->IsFailure()) return result; 2032 if (result->IsFailure()) return result;
2029 2033
2030 reinterpret_cast<Array*>(result)->set_map(byte_array_map()); 2034 reinterpret_cast<Array*>(result)->set_map(byte_array_map());
2031 reinterpret_cast<Array*>(result)->set_length(length); 2035 reinterpret_cast<Array*>(result)->set_length(length);
2032 return result; 2036 return result;
2033 } 2037 }
2034 2038
2035 2039
2036 Object* Heap::AllocateByteArray(int length) { 2040 Object* Heap::AllocateByteArray(int length) {
2041 if (length < 0 || length > ByteArray::kMaxLength) {
2042 return Failure::OutOfMemoryException();
2043 }
2037 int size = ByteArray::SizeFor(length); 2044 int size = ByteArray::SizeFor(length);
2038 AllocationSpace space = 2045 AllocationSpace space =
2039 (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : NEW_SPACE; 2046 (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : NEW_SPACE;
2040 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE); 2047 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
2041 if (result->IsFailure()) return result; 2048 if (result->IsFailure()) return result;
2042 2049
2043 reinterpret_cast<Array*>(result)->set_map(byte_array_map()); 2050 reinterpret_cast<Array*>(result)->set_map(byte_array_map());
2044 reinterpret_cast<Array*>(result)->set_length(length); 2051 reinterpret_cast<Array*>(result)->set_length(length);
2045 return result; 2052 return result;
2046 } 2053 }
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
2629 if (map == external_ascii_string_map()) return external_ascii_symbol_map(); 2636 if (map == external_ascii_string_map()) return external_ascii_symbol_map();
2630 2637
2631 // No match found. 2638 // No match found.
2632 return NULL; 2639 return NULL;
2633 } 2640 }
2634 2641
2635 2642
2636 Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, 2643 Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
2637 int chars, 2644 int chars,
2638 uint32_t hash_field) { 2645 uint32_t hash_field) {
2646 ASSERT(chars >= 0);
2639 // Ensure the chars matches the number of characters in the buffer. 2647 // Ensure the chars matches the number of characters in the buffer.
2640 ASSERT(static_cast<unsigned>(chars) == buffer->Length()); 2648 ASSERT(static_cast<unsigned>(chars) == buffer->Length());
2641 // Determine whether the string is ascii. 2649 // Determine whether the string is ascii.
2642 bool is_ascii = true; 2650 bool is_ascii = true;
2643 while (buffer->has_more() && is_ascii) { 2651 while (buffer->has_more()) {
2644 if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) is_ascii = false; 2652 if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) {
2653 is_ascii = false;
2654 break;
2655 }
2645 } 2656 }
2646 buffer->Rewind(); 2657 buffer->Rewind();
2647 2658
2648 // Compute map and object size. 2659 // Compute map and object size.
2649 int size; 2660 int size;
2650 Map* map; 2661 Map* map;
2651 2662
2652 if (is_ascii) { 2663 if (is_ascii) {
2664 if (chars > SeqAsciiString::kMaxLength) {
2665 return Failure::OutOfMemoryException();
2666 }
2653 map = ascii_symbol_map(); 2667 map = ascii_symbol_map();
2654 size = SeqAsciiString::SizeFor(chars); 2668 size = SeqAsciiString::SizeFor(chars);
2655 } else { 2669 } else {
2670 if (chars > SeqTwoByteString::kMaxLength) {
2671 return Failure::OutOfMemoryException();
2672 }
2656 map = symbol_map(); 2673 map = symbol_map();
2657 size = SeqTwoByteString::SizeFor(chars); 2674 size = SeqTwoByteString::SizeFor(chars);
2658 } 2675 }
2659 2676
2660 // Allocate string. 2677 // Allocate string.
2661 Object* result = (size > MaxObjectSizeInPagedSpace()) 2678 Object* result = (size > MaxObjectSizeInPagedSpace())
2662 ? lo_space_->AllocateRaw(size) 2679 ? lo_space_->AllocateRaw(size)
2663 : old_data_space_->AllocateRaw(size); 2680 : old_data_space_->AllocateRaw(size);
2664 if (result->IsFailure()) return result; 2681 if (result->IsFailure()) return result;
2665 2682
2666 reinterpret_cast<HeapObject*>(result)->set_map(map); 2683 reinterpret_cast<HeapObject*>(result)->set_map(map);
2667 // Set length and hash fields of the allocated string. 2684 // Set length and hash fields of the allocated string.
2668 String* answer = String::cast(result); 2685 String* answer = String::cast(result);
2669 answer->set_length(chars); 2686 answer->set_length(chars);
2670 answer->set_hash_field(hash_field); 2687 answer->set_hash_field(hash_field);
2671 2688
2672 ASSERT_EQ(size, answer->Size()); 2689 ASSERT_EQ(size, answer->Size());
2673 2690
2674 // Fill in the characters. 2691 // Fill in the characters.
2675 for (int i = 0; i < chars; i++) { 2692 for (int i = 0; i < chars; i++) {
2676 answer->Set(i, buffer->GetNext()); 2693 answer->Set(i, buffer->GetNext());
2677 } 2694 }
2678 return answer; 2695 return answer;
2679 } 2696 }
2680 2697
2681 2698
2682 Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { 2699 Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
2700 if (length < 0 || length > SeqAsciiString::kMaxLength) {
2701 return Failure::OutOfMemoryException();
2702 }
2703
2683 int size = SeqAsciiString::SizeFor(length); 2704 int size = SeqAsciiString::SizeFor(length);
2705 ASSERT(size <= SeqAsciiString::kMaxSize);
2706
2684 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2707 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
2685 AllocationSpace retry_space = OLD_DATA_SPACE; 2708 AllocationSpace retry_space = OLD_DATA_SPACE;
2686 2709
2687 if (space == NEW_SPACE) { 2710 if (space == NEW_SPACE) {
2688 if (size > kMaxObjectSizeInNewSpace) { 2711 if (size > kMaxObjectSizeInNewSpace) {
2689 // Allocate in large object space, retry space will be ignored. 2712 // Allocate in large object space, retry space will be ignored.
2690 space = LO_SPACE; 2713 space = LO_SPACE;
2691 } else if (size > MaxObjectSizeInPagedSpace()) { 2714 } else if (size > MaxObjectSizeInPagedSpace()) {
2692 // Allocate in new space, retry in large object space. 2715 // Allocate in new space, retry in large object space.
2693 retry_space = LO_SPACE; 2716 retry_space = LO_SPACE;
2694 } 2717 }
2695 } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) { 2718 } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) {
2696 space = LO_SPACE; 2719 space = LO_SPACE;
2697 } 2720 }
2698 Object* result = AllocateRaw(size, space, retry_space); 2721 Object* result = AllocateRaw(size, space, retry_space);
2699 if (result->IsFailure()) return result; 2722 if (result->IsFailure()) return result;
2700 2723
2701 // Partially initialize the object. 2724 // Partially initialize the object.
2702 HeapObject::cast(result)->set_map(ascii_string_map()); 2725 HeapObject::cast(result)->set_map(ascii_string_map());
2703 String::cast(result)->set_length(length); 2726 String::cast(result)->set_length(length);
2704 String::cast(result)->set_hash_field(String::kEmptyHashField); 2727 String::cast(result)->set_hash_field(String::kEmptyHashField);
2705 ASSERT_EQ(size, HeapObject::cast(result)->Size()); 2728 ASSERT_EQ(size, HeapObject::cast(result)->Size());
2706 return result; 2729 return result;
2707 } 2730 }
2708 2731
2709 2732
2710 Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { 2733 Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) {
2734 if (length < 0 || length > SeqTwoByteString::kMaxLength) {
2735 return Failure::OutOfMemoryException();
2736 }
2711 int size = SeqTwoByteString::SizeFor(length); 2737 int size = SeqTwoByteString::SizeFor(length);
2738 ASSERT(size <= SeqTwoByteString::kMaxSize);
2712 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2739 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
2713 AllocationSpace retry_space = OLD_DATA_SPACE; 2740 AllocationSpace retry_space = OLD_DATA_SPACE;
2714 2741
2715 if (space == NEW_SPACE) { 2742 if (space == NEW_SPACE) {
2716 if (size > kMaxObjectSizeInNewSpace) { 2743 if (size > kMaxObjectSizeInNewSpace) {
2717 // Allocate in large object space, retry space will be ignored. 2744 // Allocate in large object space, retry space will be ignored.
2718 space = LO_SPACE; 2745 space = LO_SPACE;
2719 } else if (size > MaxObjectSizeInPagedSpace()) { 2746 } else if (size > MaxObjectSizeInPagedSpace()) {
2720 // Allocate in new space, retry in large object space. 2747 // Allocate in new space, retry in large object space.
2721 retry_space = LO_SPACE; 2748 retry_space = LO_SPACE;
(...skipping 18 matching lines...) Expand all
2740 Object* result = AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE); 2767 Object* result = AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
2741 if (result->IsFailure()) return result; 2768 if (result->IsFailure()) return result;
2742 // Initialize the object. 2769 // Initialize the object.
2743 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); 2770 reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
2744 reinterpret_cast<Array*>(result)->set_length(0); 2771 reinterpret_cast<Array*>(result)->set_length(0);
2745 return result; 2772 return result;
2746 } 2773 }
2747 2774
2748 2775
2749 Object* Heap::AllocateRawFixedArray(int length) { 2776 Object* Heap::AllocateRawFixedArray(int length) {
2777 if (length < 0 || length > FixedArray::kMaxLength) {
2778 return Failure::OutOfMemoryException();
2779 }
2750 // Use the general function if we're forced to always allocate. 2780 // Use the general function if we're forced to always allocate.
2751 if (always_allocate()) return AllocateFixedArray(length, TENURED); 2781 if (always_allocate()) return AllocateFixedArray(length, TENURED);
2752 // Allocate the raw data for a fixed array. 2782 // Allocate the raw data for a fixed array.
2753 int size = FixedArray::SizeFor(length); 2783 int size = FixedArray::SizeFor(length);
2754 return size <= kMaxObjectSizeInNewSpace 2784 return size <= kMaxObjectSizeInNewSpace
2755 ? new_space_.AllocateRaw(size) 2785 ? new_space_.AllocateRaw(size)
2756 : lo_space_->AllocateRawFixedArray(size); 2786 : lo_space_->AllocateRawFixedArray(size);
2757 } 2787 }
2758 2788
2759 2789
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 // Initialize body. 2821 // Initialize body.
2792 for (int index = 0; index < length; index++) { 2822 for (int index = 0; index < length; index++) {
2793 array->set(index, value, SKIP_WRITE_BARRIER); 2823 array->set(index, value, SKIP_WRITE_BARRIER);
2794 } 2824 }
2795 } 2825 }
2796 return result; 2826 return result;
2797 } 2827 }
2798 2828
2799 2829
2800 Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { 2830 Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
2831 ASSERT(length >= 0);
2801 ASSERT(empty_fixed_array()->IsFixedArray()); 2832 ASSERT(empty_fixed_array()->IsFixedArray());
2833 if (length < 0 || length > FixedArray::kMaxLength) {
2834 return Failure::OutOfMemoryException();
2835 }
2802 if (length == 0) return empty_fixed_array(); 2836 if (length == 0) return empty_fixed_array();
2803 2837
2804 AllocationSpace space = 2838 AllocationSpace space =
2805 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; 2839 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
2806 int size = FixedArray::SizeFor(length); 2840 int size = FixedArray::SizeFor(length);
2807 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) { 2841 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) {
2808 // Too big for new space. 2842 // Too big for new space.
2809 space = LO_SPACE; 2843 space = LO_SPACE;
2810 } else if (space == OLD_POINTER_SPACE && 2844 } else if (space == OLD_POINTER_SPACE &&
2811 size > MaxObjectSizeInPagedSpace()) { 2845 size > MaxObjectSizeInPagedSpace()) {
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after
4081 void ExternalStringTable::TearDown() { 4115 void ExternalStringTable::TearDown() {
4082 new_space_strings_.Free(); 4116 new_space_strings_.Free();
4083 old_space_strings_.Free(); 4117 old_space_strings_.Free();
4084 } 4118 }
4085 4119
4086 4120
4087 List<Object*> ExternalStringTable::new_space_strings_; 4121 List<Object*> ExternalStringTable::new_space_strings_;
4088 List<Object*> ExternalStringTable::old_space_strings_; 4122 List<Object*> ExternalStringTable::old_space_strings_;
4089 4123
4090 } } // namespace v8::internal 4124 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698