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

Side by Side Diff: runtime/vm/freelist.cc

Issue 150563007: Fix crash bug in free list when allocating write protected memory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: addressed commment Created 6 years, 10 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
« no previous file with comments | « runtime/vm/freelist.h ('k') | runtime/vm/freelist_test.cc » ('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 (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/freelist.h" 5 #include "vm/freelist.h"
6 6
7 #include <map> 7 #include <map>
8 #include <utility> 8 #include <utility>
9 9
10 #include "vm/bit_set.h" 10 #include "vm/bit_set.h"
(...skipping 25 matching lines...) Expand all
36 // writable. 36 // writable.
37 } 37 }
38 38
39 39
40 void FreeListElement::InitOnce() { 40 void FreeListElement::InitOnce() {
41 ASSERT(sizeof(FreeListElement) == kObjectAlignment); 41 ASSERT(sizeof(FreeListElement) == kObjectAlignment);
42 ASSERT(OFFSET_OF(FreeListElement, tags_) == Object::tags_offset()); 42 ASSERT(OFFSET_OF(FreeListElement, tags_) == Object::tags_offset());
43 } 43 }
44 44
45 45
46 intptr_t FreeListElement::HeaderSizeFor(intptr_t size) {
47 if (size == 0) return 0;
48 return ((size > RawObject::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize;
49 }
50
51
46 FreeList::FreeList() { 52 FreeList::FreeList() {
47 Reset(); 53 Reset();
48 } 54 }
49 55
50 56
51 FreeList::~FreeList() { 57 FreeList::~FreeList() {
52 // Nothing to release. 58 // Nothing to release.
53 } 59 }
54 60
55 61
56 uword FreeList::TryAllocate(intptr_t size, bool is_protected) { 62 uword FreeList::TryAllocate(intptr_t size, bool is_protected) {
57 // Precondition: is_protected is false or else all free list elements are 63 // Precondition: is_protected is false or else all free list elements are
58 // in non-writable pages. 64 // in non-writable pages.
59 65
60 // Postcondition: if allocation succeeds, the allocated block is writable. 66 // Postcondition: if allocation succeeds, the allocated block is writable.
61 int index = IndexForSize(size); 67 int index = IndexForSize(size);
62 if ((index != kNumLists) && free_map_.Test(index)) { 68 if ((index != kNumLists) && free_map_.Test(index)) {
63 FreeListElement* element = DequeueElement(index); 69 FreeListElement* element = DequeueElement(index);
64 if (is_protected) { 70 if (is_protected) {
65 bool status = 71 bool status =
66 VirtualMemory::Protect(reinterpret_cast<void*>(element), 72 VirtualMemory::Protect(reinterpret_cast<void*>(element),
67 size, 73 size,
68 VirtualMemory::kReadWrite /*Execute*/); 74 VirtualMemory::kReadWrite);
69 ASSERT(status); 75 ASSERT(status);
70 } 76 }
71 return reinterpret_cast<uword>(element); 77 return reinterpret_cast<uword>(element);
72 } 78 }
73 79
74 if ((index + 1) < kNumLists) { 80 if ((index + 1) < kNumLists) {
75 intptr_t next_index = free_map_.Next(index + 1); 81 intptr_t next_index = free_map_.Next(index + 1);
76 if (next_index != -1) { 82 if (next_index != -1) {
77 // Dequeue an element from the list, split and enqueue the remainder in 83 // Dequeue an element from the list, split and enqueue the remainder in
78 // the appropriate list. 84 // the appropriate list.
79 FreeListElement* element = DequeueElement(next_index); 85 FreeListElement* element = DequeueElement(next_index);
80 if (is_protected) { 86 if (is_protected) {
81 // Make the allocated block and the header of the remainder element 87 // Make the allocated block and the header of the remainder element
82 // writable. The remainder will be non-writable if necessary after 88 // writable. The remainder will be non-writable if necessary after
83 // the call to SplitElementAfterAndEnqueue. 89 // the call to SplitElementAfterAndEnqueue.
84 // If the remainder size is zero, only the element itself needs to 90 // If the remainder size is zero, only the element itself needs to
85 // be made writable. 91 // be made writable.
86 intptr_t remainder_size = element->Size() - size; 92 intptr_t remainder_size = element->Size() - size;
87 intptr_t region_size = size + 93 intptr_t region_size =
88 ((remainder_size > 0) ? FreeListElement::kHeaderSize : 0); 94 size + FreeListElement::HeaderSizeFor(remainder_size);
89 bool status = 95 bool status =
90 VirtualMemory::Protect(reinterpret_cast<void*>(element), 96 VirtualMemory::Protect(reinterpret_cast<void*>(element),
91 region_size, 97 region_size,
92 VirtualMemory::kReadWrite /*Execute*/); 98 VirtualMemory::kReadWrite);
93 ASSERT(status); 99 ASSERT(status);
94 } 100 }
95 SplitElementAfterAndEnqueue(element, size, is_protected); 101 SplitElementAfterAndEnqueue(element, size, is_protected);
96 return reinterpret_cast<uword>(element); 102 return reinterpret_cast<uword>(element);
97 } 103 }
98 } 104 }
99 105
100 FreeListElement* previous = NULL; 106 FreeListElement* previous = NULL;
101 FreeListElement* current = free_lists_[kNumLists]; 107 FreeListElement* current = free_lists_[kNumLists];
102 while (current != NULL) { 108 while (current != NULL) {
103 if (current->Size() >= size) { 109 if (current->Size() >= size) {
104 // Found an element large enough to hold the requested size. Dequeue, 110 // Found an element large enough to hold the requested size. Dequeue,
105 // split and enqueue the remainder. 111 // split and enqueue the remainder.
112 intptr_t remainder_size = current->Size() - size;
113 intptr_t region_size =
114 size + FreeListElement::HeaderSizeFor(remainder_size);
106 if (is_protected) { 115 if (is_protected) {
107 // Make the allocated block and the header of the remainder element 116 // Make the allocated block and the header of the remainder element
108 // writable. The remainder will be non-writable if necessary after 117 // writable. The remainder will be non-writable if necessary after
109 // the call to SplitElementAfterAndEnqueue. 118 // the call to SplitElementAfterAndEnqueue.
110 intptr_t remainder_size = current->Size() - size;
111 intptr_t region_size = size +
112 ((remainder_size > 0) ? FreeListElement::kHeaderSize : 0);
113 bool status = 119 bool status =
114 VirtualMemory::Protect(reinterpret_cast<void*>(current), 120 VirtualMemory::Protect(reinterpret_cast<void*>(current),
115 region_size, 121 region_size,
116 VirtualMemory::kReadWrite /*Execute*/); 122 VirtualMemory::kReadWrite);
117 ASSERT(status); 123 ASSERT(status);
118 } 124 }
125
119 if (previous == NULL) { 126 if (previous == NULL) {
120 free_lists_[kNumLists] = current->next(); 127 free_lists_[kNumLists] = current->next();
121 } else { 128 } else {
122 // If the previous free list element's next field is protected, it 129 // If the previous free list element's next field is protected, it
123 // needs to be unprotected before storing to it and reprotected 130 // needs to be unprotected before storing to it and reprotected
124 // after. 131 // after.
125 bool target_is_protected = false; 132 bool target_is_protected = false;
126 uword target_address = NULL; 133 uword target_address = NULL;
127 if (is_protected) { 134 if (is_protected) {
128 uword writable_start = reinterpret_cast<uword>(current); 135 uword writable_start = reinterpret_cast<uword>(current);
129 uword writable_end = 136 uword writable_end = writable_start + region_size - 1;
130 writable_start + size + FreeListElement::kHeaderSize - 1;
131 target_address = previous->next_address(); 137 target_address = previous->next_address();
132 target_is_protected = 138 target_is_protected =
133 !VirtualMemory::InSamePage(target_address, writable_start) && 139 !VirtualMemory::InSamePage(target_address, writable_start) &&
134 !VirtualMemory::InSamePage(target_address, writable_end); 140 !VirtualMemory::InSamePage(target_address, writable_end);
135 } 141 }
136 if (target_is_protected) { 142 if (target_is_protected) {
137 bool status = 143 bool status =
138 VirtualMemory::Protect(reinterpret_cast<void*>(target_address), 144 VirtualMemory::Protect(reinterpret_cast<void*>(target_address),
139 kWordSize, 145 kWordSize,
140 VirtualMemory::kReadWrite /*Execute*/); 146 VirtualMemory::kReadWrite);
141 ASSERT(status); 147 ASSERT(status);
142 } 148 }
143 previous->set_next(current->next()); 149 previous->set_next(current->next());
144 if (target_is_protected) { 150 if (target_is_protected) {
145 bool status = 151 bool status =
146 VirtualMemory::Protect(reinterpret_cast<void*>(target_address), 152 VirtualMemory::Protect(reinterpret_cast<void*>(target_address),
147 kWordSize, 153 kWordSize,
148 VirtualMemory::kReadExecute); 154 VirtualMemory::kReadExecute);
149 ASSERT(status); 155 ASSERT(status);
150 } 156 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) { 317 !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) {
312 bool status = 318 bool status =
313 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address), 319 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address),
314 remainder_size, 320 remainder_size,
315 VirtualMemory::kReadExecute); 321 VirtualMemory::kReadExecute);
316 ASSERT(status); 322 ASSERT(status);
317 } 323 }
318 } 324 }
319 325
320 } // namespace dart 326 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/freelist.h ('k') | runtime/vm/freelist_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698