Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 Google Inc. All Rights Reserved. | 1 // Copyright 2014 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 shift = (n > 0xF) << 2; | 59 shift = (n > 0xF) << 2; |
| 60 n >>= shift; | 60 n >>= shift; |
| 61 r |= shift; | 61 r |= shift; |
| 62 shift = (n > 0x3) << 1; | 62 shift = (n > 0x3) << 1; |
| 63 n >>= shift; | 63 n >>= shift; |
| 64 r |= shift; | 64 r |= shift; |
| 65 r |= (n >> 1); | 65 r |= (n >> 1); |
| 66 return r; | 66 return r; |
| 67 } | 67 } |
| 68 | 68 |
| 69 // Try to do an unguarded allocation. | |
| 70 // @param heap_interface The heap that should serve the allocation. | |
| 71 // @param shadow The shadow memory. | |
| 72 // @param bytes The size of the allocation. | |
| 73 // @returns a pointer to the allocation on success, nullptr otherwise. | |
| 74 void* DoUnguardedAllocation(BlockHeapInterface* heap_interface, | |
| 75 Shadow* shadow, | |
| 76 uint32_t bytes) { | |
| 77 void* alloc = heap_interface->Allocate(bytes); | |
| 78 if ((heap_interface->GetHeapFeatures() & | |
| 79 HeapInterface::kHeapReportsReservations) != 0) { | |
| 80 shadow->Unpoison(alloc, bytes); | |
| 81 } | |
| 82 return alloc; | |
| 83 } | |
| 84 | |
| 69 } // namespace | 85 } // namespace |
| 70 | 86 |
| 71 BlockHeapManager::BlockHeapManager(Shadow* shadow, | 87 BlockHeapManager::BlockHeapManager(Shadow* shadow, |
| 72 StackCaptureCache* stack_cache, | 88 StackCaptureCache* stack_cache, |
| 73 MemoryNotifierInterface* memory_notifier) | 89 MemoryNotifierInterface* memory_notifier) |
| 74 : shadow_(shadow), | 90 : shadow_(shadow), |
| 75 stack_cache_(stack_cache), | 91 stack_cache_(stack_cache), |
| 76 memory_notifier_(memory_notifier), | 92 memory_notifier_(memory_notifier), |
| 77 initialized_(false), | 93 initialized_(false), |
| 78 process_heap_(nullptr), | 94 process_heap_(nullptr), |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 172 return true; | 188 return true; |
| 173 } | 189 } |
| 174 | 190 |
| 175 void* BlockHeapManager::Allocate(HeapId heap_id, uint32_t bytes) { | 191 void* BlockHeapManager::Allocate(HeapId heap_id, uint32_t bytes) { |
| 176 DCHECK(initialized_); | 192 DCHECK(initialized_); |
| 177 DCHECK(IsValidHeapId(heap_id, false)); | 193 DCHECK(IsValidHeapId(heap_id, false)); |
| 178 | 194 |
| 179 // Some allocations can pass through without instrumentation. | 195 // Some allocations can pass through without instrumentation. |
| 180 if (parameters_.allocation_guard_rate < 1.0 && | 196 if (parameters_.allocation_guard_rate < 1.0 && |
| 181 base::RandDouble() >= parameters_.allocation_guard_rate) { | 197 base::RandDouble() >= parameters_.allocation_guard_rate) { |
| 182 BlockHeapInterface* heap = GetHeapFromId(heap_id); | 198 return DoUnguardedAllocation(GetHeapFromId(heap_id), shadow_, bytes); |
| 183 void* alloc = heap->Allocate(bytes); | |
| 184 if ((heap->GetHeapFeatures() & | |
| 185 HeapInterface::kHeapReportsReservations) != 0) { | |
| 186 shadow_->Unpoison(alloc, bytes); | |
| 187 } | |
| 188 return alloc; | |
| 189 } | 199 } |
| 190 | 200 |
| 191 // Capture the current stack. InitFromStack is inlined to preserve the | 201 // Capture the current stack. InitFromStack is inlined to preserve the |
| 192 // greatest number of stack frames. | 202 // greatest number of stack frames. |
| 193 common::StackCapture stack; | 203 common::StackCapture stack; |
| 194 stack.InitFromStack(); | 204 stack.InitFromStack(); |
| 195 | 205 |
| 196 // Build the set of heaps that will be used to satisfy the allocation. This | 206 // Build the set of heaps that will be used to satisfy the allocation. This |
| 197 // is a stack of heaps, and they will be tried in the reverse order they are | 207 // is a stack of heaps, and they will be tried in the reverse order they are |
| 198 // inserted. | 208 // inserted. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 219 bytes, | 229 bytes, |
| 220 0, | 230 0, |
| 221 parameters_.trailer_padding_size + sizeof(BlockTrailer), | 231 parameters_.trailer_padding_size + sizeof(BlockTrailer), |
| 222 &block_layout); | 232 &block_layout); |
| 223 if (alloc != nullptr) { | 233 if (alloc != nullptr) { |
| 224 heap_id = heaps[i]; | 234 heap_id = heaps[i]; |
| 225 break; | 235 break; |
| 226 } | 236 } |
| 227 } | 237 } |
| 228 | 238 |
| 229 // The allocation can fail if we're out of memory. | 239 // The allocation might fail because its size exceed the maximum size that |
|
Sigurður Ásgeirsson
2016/11/25 18:16:11
It would IMHO make much more sense, and be much si
Sébastien Marchand
2016/11/25 21:14:57
I'm not sure, we had some CF test cases who alloca
| |
| 240 // we can represent in the BlockHeader structure, try to do an unguarded | |
| 241 // allocation. | |
| 230 if (alloc == nullptr) | 242 if (alloc == nullptr) |
| 231 return nullptr; | 243 return DoUnguardedAllocation(GetHeapFromId(heap_id), shadow_, bytes); |
| 232 | 244 |
| 233 DCHECK_NE(static_cast<void*>(nullptr), alloc); | 245 DCHECK_NE(static_cast<void*>(nullptr), alloc); |
| 234 DCHECK_EQ(0u, reinterpret_cast<size_t>(alloc) % kShadowRatio); | 246 DCHECK_EQ(0u, reinterpret_cast<size_t>(alloc) % kShadowRatio); |
| 235 BlockInfo block = {}; | 247 BlockInfo block = {}; |
| 236 BlockInitialize(block_layout, alloc, &block); | 248 BlockInitialize(block_layout, alloc, &block); |
| 237 | 249 |
| 238 // Poison the redzones in the shadow memory as early as possible. | 250 // Poison the redzones in the shadow memory as early as possible. |
| 239 shadow_->PoisonAllocatedBlock(block); | 251 shadow_->PoisonAllocatedBlock(block); |
| 240 | 252 |
| 241 block.header->alloc_stack = stack_cache_->SaveStackTrace(stack); | 253 block.header->alloc_stack = stack_cache_->SaveStackTrace(stack); |
| (...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1112 if (trailer_has_valid_heap_id) | 1124 if (trailer_has_valid_heap_id) |
| 1113 return block_info->trailer->heap_id; | 1125 return block_info->trailer->heap_id; |
| 1114 | 1126 |
| 1115 // Unfortunately, there's no way to know which heap this block belongs to. | 1127 // Unfortunately, there's no way to know which heap this block belongs to. |
| 1116 return 0; | 1128 return 0; |
| 1117 } | 1129 } |
| 1118 | 1130 |
| 1119 } // namespace heap_managers | 1131 } // namespace heap_managers |
| 1120 } // namespace asan | 1132 } // namespace asan |
| 1121 } // namespace agent | 1133 } // namespace agent |
| OLD | NEW |