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

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: Fix gcc compiler warnings 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 return ((size > RawObject::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize;
srdjan 2014/02/11 21:45:40 Could you include: if (size == 0) return 0, and re
siva 2014/02/11 23:36:43 Agree.
Florian Schneider 2014/02/12 11:32:35 Done.
48 }
49
50
46 FreeList::FreeList() { 51 FreeList::FreeList() {
47 Reset(); 52 Reset();
48 } 53 }
49 54
50 55
51 FreeList::~FreeList() { 56 FreeList::~FreeList() {
52 // Nothing to release. 57 // Nothing to release.
53 } 58 }
54 59
55 60
56 uword FreeList::TryAllocate(intptr_t size, bool is_protected) { 61 uword FreeList::TryAllocate(intptr_t size, bool is_protected) {
57 // Precondition: is_protected is false or else all free list elements are 62 // Precondition: is_protected is false or else all free list elements are
58 // in non-writable pages. 63 // in non-writable pages.
59 64
60 // Postcondition: if allocation succeeds, the allocated block is writable. 65 // Postcondition: if allocation succeeds, the allocated block is writable.
61 int index = IndexForSize(size); 66 int index = IndexForSize(size);
62 if ((index != kNumLists) && free_map_.Test(index)) { 67 if ((index != kNumLists) && free_map_.Test(index)) {
63 FreeListElement* element = DequeueElement(index); 68 FreeListElement* element = DequeueElement(index);
64 if (is_protected) { 69 if (is_protected) {
65 bool status = 70 bool status =
66 VirtualMemory::Protect(reinterpret_cast<void*>(element), 71 VirtualMemory::Protect(reinterpret_cast<void*>(element),
67 size, 72 size,
68 VirtualMemory::kReadWrite /*Execute*/); 73 VirtualMemory::kReadWrite);
69 ASSERT(status); 74 ASSERT(status);
70 } 75 }
71 return reinterpret_cast<uword>(element); 76 return reinterpret_cast<uword>(element);
72 } 77 }
73 78
74 if ((index + 1) < kNumLists) { 79 if ((index + 1) < kNumLists) {
75 intptr_t next_index = free_map_.Next(index + 1); 80 intptr_t next_index = free_map_.Next(index + 1);
76 if (next_index != -1) { 81 if (next_index != -1) {
77 // Dequeue an element from the list, split and enqueue the remainder in 82 // Dequeue an element from the list, split and enqueue the remainder in
78 // the appropriate list. 83 // the appropriate list.
79 FreeListElement* element = DequeueElement(next_index); 84 FreeListElement* element = DequeueElement(next_index);
80 if (is_protected) { 85 if (is_protected) {
81 // Make the allocated block and the header of the remainder element 86 // Make the allocated block and the header of the remainder element
82 // writable. The remainder will be non-writable if necessary after 87 // writable. The remainder will be non-writable if necessary after
83 // the call to SplitElementAfterAndEnqueue. 88 // the call to SplitElementAfterAndEnqueue.
84 // If the remainder size is zero, only the element itself needs to 89 // If the remainder size is zero, only the element itself needs to
85 // be made writable. 90 // be made writable.
86 intptr_t remainder_size = element->Size() - size; 91 intptr_t remainder_size = element->Size() - size;
87 intptr_t region_size = size + 92 intptr_t region_size = size +
88 ((remainder_size > 0) ? FreeListElement::kHeaderSize : 0); 93 ((remainder_size > 0)
94 ? FreeListElement::HeaderSizeFor(remainder_size) : 0);
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 = size +
114 ((remainder_size > 0)
115 ? FreeListElement::HeaderSizeFor(remainder_size) : 0);
106 if (is_protected) { 116 if (is_protected) {
107 // Make the allocated block and the header of the remainder element 117 // Make the allocated block and the header of the remainder element
108 // writable. The remainder will be non-writable if necessary after 118 // writable. The remainder will be non-writable if necessary after
109 // the call to SplitElementAfterAndEnqueue. 119 // 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 = 120 bool status =
114 VirtualMemory::Protect(reinterpret_cast<void*>(current), 121 VirtualMemory::Protect(reinterpret_cast<void*>(current),
115 region_size, 122 region_size,
116 VirtualMemory::kReadWrite /*Execute*/); 123 VirtualMemory::kReadWrite);
117 ASSERT(status); 124 ASSERT(status);
118 } 125 }
126
119 if (previous == NULL) { 127 if (previous == NULL) {
120 free_lists_[kNumLists] = current->next(); 128 free_lists_[kNumLists] = current->next();
121 } else { 129 } else {
122 // If the previous free list element's next field is protected, it 130 // If the previous free list element's next field is protected, it
123 // needs to be unprotected before storing to it and reprotected 131 // needs to be unprotected before storing to it and reprotected
124 // after. 132 // after.
125 bool target_is_protected = false; 133 bool target_is_protected = false;
126 uword target_address = NULL; 134 uword target_address = NULL;
127 if (is_protected) { 135 if (is_protected) {
128 uword writable_start = reinterpret_cast<uword>(current); 136 uword writable_start = reinterpret_cast<uword>(current);
129 uword writable_end = 137 uword writable_end = writable_start + region_size - 1;
130 writable_start + size + FreeListElement::kHeaderSize - 1;
131 target_address = previous->next_address(); 138 target_address = previous->next_address();
132 target_is_protected = 139 target_is_protected =
133 !VirtualMemory::InSamePage(target_address, writable_start) && 140 !VirtualMemory::InSamePage(target_address, writable_start) &&
134 !VirtualMemory::InSamePage(target_address, writable_end); 141 !VirtualMemory::InSamePage(target_address, writable_end);
135 } 142 }
136 if (target_is_protected) { 143 if (target_is_protected) {
137 bool status = 144 bool status =
138 VirtualMemory::Protect(reinterpret_cast<void*>(target_address), 145 VirtualMemory::Protect(reinterpret_cast<void*>(target_address),
139 kWordSize, 146 kWordSize,
140 VirtualMemory::kReadWrite /*Execute*/); 147 VirtualMemory::kReadWrite);
141 ASSERT(status); 148 ASSERT(status);
142 } 149 }
143 previous->set_next(current->next()); 150 previous->set_next(current->next());
144 if (target_is_protected) { 151 if (target_is_protected) {
145 bool status = 152 bool status =
146 VirtualMemory::Protect(reinterpret_cast<void*>(target_address), 153 VirtualMemory::Protect(reinterpret_cast<void*>(target_address),
147 kWordSize, 154 kWordSize,
148 VirtualMemory::kReadExecute); 155 VirtualMemory::kReadExecute);
149 ASSERT(status); 156 ASSERT(status);
150 } 157 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) { 318 !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) {
312 bool status = 319 bool status =
313 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address), 320 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address),
314 remainder_size, 321 remainder_size,
315 VirtualMemory::kReadExecute); 322 VirtualMemory::kReadExecute);
316 ASSERT(status); 323 ASSERT(status);
317 } 324 }
318 } 325 }
319 326
320 } // namespace dart 327 } // 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