OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process/memory.h" | 5 #include "base/process/memory.h" |
6 | 6 |
7 // AddressSanitizer handles heap corruption, and on 64 bit Macs, the malloc | |
8 // system automatically abort()s on heap corruption. | |
9 #if !defined(ADDRESS_SANITIZER) && ARCH_CPU_32_BITS | |
10 #define HANDLE_MEMORY_CORRUPTION_MANUALLY | |
11 #endif | |
12 | |
7 #include <CoreFoundation/CoreFoundation.h> | 13 #include <CoreFoundation/CoreFoundation.h> |
8 #include <errno.h> | 14 #include <errno.h> |
9 #include <mach/mach.h> | 15 #include <mach/mach.h> |
10 #include <mach/mach_vm.h> | 16 #include <mach/mach_vm.h> |
11 #include <malloc/malloc.h> | 17 #include <malloc/malloc.h> |
12 #import <objc/runtime.h> | 18 #import <objc/runtime.h> |
13 | 19 |
14 #include <new> | 20 #include <new> |
15 | 21 |
16 #include "base/lazy_instance.h" | 22 #include "base/lazy_instance.h" |
17 #include "base/logging.h" | 23 #include "base/logging.h" |
18 #include "base/mac/mac_util.h" | 24 #include "base/mac/mac_util.h" |
19 #include "base/mac/mach_logging.h" | 25 #include "base/mac/mach_logging.h" |
20 #include "base/scoped_clear_errno.h" | 26 #include "base/scoped_clear_errno.h" |
21 #include "third_party/apple_apsl/CFBase.h" | 27 #include "third_party/apple_apsl/CFBase.h" |
22 #include "third_party/apple_apsl/malloc.h" | 28 #include "third_party/apple_apsl/malloc.h" |
23 | 29 |
24 #if ARCH_CPU_32_BITS | 30 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
25 #include <dlfcn.h> | 31 #include <dlfcn.h> |
26 #include <mach-o/nlist.h> | 32 #include <mach-o/nlist.h> |
27 | 33 |
28 #include "base/threading/thread_local.h" | 34 #include "base/threading/thread_local.h" |
29 #include "third_party/mach_override/mach_override.h" | 35 #include "third_party/mach_override/mach_override.h" |
30 #endif // ARCH_CPU_32_BITS | 36 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
31 | 37 |
32 namespace base { | 38 namespace base { |
33 | 39 |
34 // These are helpers for EnableTerminationOnHeapCorruption, which is a no-op | 40 // These are helpers for EnableTerminationOnHeapCorruption, which is a no-op |
35 // on 64 bit Macs. | 41 // on 64 bit Macs. |
36 #if ARCH_CPU_32_BITS | 42 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
37 namespace { | 43 namespace { |
38 | 44 |
39 // Finds the library path for malloc() and thus the libC part of libSystem, | 45 // Finds the library path for malloc() and thus the libC part of libSystem, |
40 // which in Lion is in a separate image. | 46 // which in Lion is in a separate image. |
41 const char* LookUpLibCPath() { | 47 const char* LookUpLibCPath() { |
42 const void* addr = reinterpret_cast<void*>(&malloc); | 48 const void* addr = reinterpret_cast<void*>(&malloc); |
43 | 49 |
44 Dl_info info; | 50 Dl_info info; |
45 if (dladdr(addr, &info)) | 51 if (dladdr(addr, &info)) |
46 return info.dli_fname; | 52 return info.dli_fname; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 // crash dump info (setting a breakpad key would re-enter the malloc | 161 // crash dump info (setting a breakpad key would re-enter the malloc |
156 // library). Max documented errno in intro(2) is actually 102, but | 162 // library). Max documented errno in intro(2) is actually 102, but |
157 // it really just needs to be "small" to stay on the right vm page. | 163 // it really just needs to be "small" to stay on the right vm page. |
158 const int kMaxErrno = 256; | 164 const int kMaxErrno = 256; |
159 char* volatile death_ptr = NULL; | 165 char* volatile death_ptr = NULL; |
160 death_ptr += std::min(errno, kMaxErrno); | 166 death_ptr += std::min(errno, kMaxErrno); |
161 *death_ptr = '!'; | 167 *death_ptr = '!'; |
162 } | 168 } |
163 | 169 |
164 } // namespace | 170 } // namespace |
165 #endif // ARCH_CPU_32_BITS | 171 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
166 | 172 |
167 void EnableTerminationOnHeapCorruption() { | 173 void EnableTerminationOnHeapCorruption() { |
168 #if defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS | 174 #if !defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
Nico
2014/07/16 19:34:24
Since the comment that used to be here is now at t
tzik
2014/07/17 08:17:27
Done.
| |
169 // AddressSanitizer handles heap corruption, and on 64 bit Macs, the malloc | |
170 // system automatically abort()s on heap corruption. | |
171 return; | 175 return; |
172 #else | 176 #else |
173 // Only override once, otherwise CrMallocErrorBreak() will recurse | 177 // Only override once, otherwise CrMallocErrorBreak() will recurse |
174 // to itself. | 178 // to itself. |
175 if (g_original_malloc_error_break) | 179 if (g_original_malloc_error_break) |
176 return; | 180 return; |
177 | 181 |
178 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); | 182 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); |
179 if (!malloc_error_break) { | 183 if (!malloc_error_break) { |
180 DLOG(WARNING) << "Could not find malloc_error_break"; | 184 DLOG(WARNING) << "Could not find malloc_error_break"; |
181 return; | 185 return; |
182 } | 186 } |
183 | 187 |
184 mach_error_t err = mach_override_ptr( | 188 mach_error_t err = mach_override_ptr( |
185 (void*)malloc_error_break, | 189 (void*)malloc_error_break, |
186 (void*)&CrMallocErrorBreak, | 190 (void*)&CrMallocErrorBreak, |
187 (void**)&g_original_malloc_error_break); | 191 (void**)&g_original_malloc_error_break); |
188 | 192 |
189 if (err != err_none) | 193 if (err != err_none) |
190 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; | 194 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; |
191 #endif // defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS | 195 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
192 } | 196 } |
193 | 197 |
194 // ------------------------------------------------------------------------ | 198 // ------------------------------------------------------------------------ |
195 | 199 |
196 namespace { | 200 namespace { |
197 | 201 |
198 bool g_oom_killer_enabled; | 202 bool g_oom_killer_enabled; |
199 | 203 |
204 #if !defined(ADDRESS_SANITIZER) | |
205 | |
200 // Starting with Mac OS X 10.7, the zone allocators set up by the system are | 206 // Starting with Mac OS X 10.7, the zone allocators set up by the system are |
201 // read-only, to prevent them from being overwritten in an attack. However, | 207 // read-only, to prevent them from being overwritten in an attack. However, |
202 // blindly unprotecting and reprotecting the zone allocators fails with | 208 // blindly unprotecting and reprotecting the zone allocators fails with |
203 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of | 209 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of |
204 // memory in its bss. Explicit saving/restoring of the protection is required. | 210 // memory in its bss. Explicit saving/restoring of the protection is required. |
205 // | 211 // |
206 // This function takes a pointer to a malloc zone, de-protects it if necessary, | 212 // This function takes a pointer to a malloc zone, de-protects it if necessary, |
207 // and returns (in the out parameters) a region of memory (if any) to be | 213 // and returns (in the out parameters) a region of memory (if any) to be |
208 // re-protected when modifications are complete. This approach assumes that | 214 // re-protected when modifications are complete. This approach assumes that |
209 // there is no contention for the protection of this memory. | 215 // there is no contention for the protection of this memory. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 | 288 |
283 malloc_type g_old_malloc_purgeable; | 289 malloc_type g_old_malloc_purgeable; |
284 calloc_type g_old_calloc_purgeable; | 290 calloc_type g_old_calloc_purgeable; |
285 valloc_type g_old_valloc_purgeable; | 291 valloc_type g_old_valloc_purgeable; |
286 free_type g_old_free_purgeable; | 292 free_type g_old_free_purgeable; |
287 realloc_type g_old_realloc_purgeable; | 293 realloc_type g_old_realloc_purgeable; |
288 memalign_type g_old_memalign_purgeable; | 294 memalign_type g_old_memalign_purgeable; |
289 | 295 |
290 void* oom_killer_malloc(struct _malloc_zone_t* zone, | 296 void* oom_killer_malloc(struct _malloc_zone_t* zone, |
291 size_t size) { | 297 size_t size) { |
292 #if ARCH_CPU_32_BITS | 298 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
293 ScopedClearErrno clear_errno; | 299 ScopedClearErrno clear_errno; |
294 #endif // ARCH_CPU_32_BITS | 300 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
295 void* result = g_old_malloc(zone, size); | 301 void* result = g_old_malloc(zone, size); |
296 if (!result && size) | 302 if (!result && size) |
297 debug::BreakDebugger(); | 303 debug::BreakDebugger(); |
298 return result; | 304 return result; |
299 } | 305 } |
300 | 306 |
301 void* oom_killer_calloc(struct _malloc_zone_t* zone, | 307 void* oom_killer_calloc(struct _malloc_zone_t* zone, |
302 size_t num_items, | 308 size_t num_items, |
303 size_t size) { | 309 size_t size) { |
304 #if ARCH_CPU_32_BITS | 310 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
305 ScopedClearErrno clear_errno; | 311 ScopedClearErrno clear_errno; |
306 #endif // ARCH_CPU_32_BITS | 312 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
307 void* result = g_old_calloc(zone, num_items, size); | 313 void* result = g_old_calloc(zone, num_items, size); |
308 if (!result && num_items && size) | 314 if (!result && num_items && size) |
309 debug::BreakDebugger(); | 315 debug::BreakDebugger(); |
310 return result; | 316 return result; |
311 } | 317 } |
312 | 318 |
313 void* oom_killer_valloc(struct _malloc_zone_t* zone, | 319 void* oom_killer_valloc(struct _malloc_zone_t* zone, |
314 size_t size) { | 320 size_t size) { |
315 #if ARCH_CPU_32_BITS | 321 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
316 ScopedClearErrno clear_errno; | 322 ScopedClearErrno clear_errno; |
317 #endif // ARCH_CPU_32_BITS | 323 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
318 void* result = g_old_valloc(zone, size); | 324 void* result = g_old_valloc(zone, size); |
319 if (!result && size) | 325 if (!result && size) |
320 debug::BreakDebugger(); | 326 debug::BreakDebugger(); |
321 return result; | 327 return result; |
322 } | 328 } |
323 | 329 |
324 void oom_killer_free(struct _malloc_zone_t* zone, | 330 void oom_killer_free(struct _malloc_zone_t* zone, |
325 void* ptr) { | 331 void* ptr) { |
326 #if ARCH_CPU_32_BITS | 332 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
327 ScopedClearErrno clear_errno; | 333 ScopedClearErrno clear_errno; |
328 #endif // ARCH_CPU_32_BITS | 334 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
329 g_old_free(zone, ptr); | 335 g_old_free(zone, ptr); |
330 } | 336 } |
331 | 337 |
332 void* oom_killer_realloc(struct _malloc_zone_t* zone, | 338 void* oom_killer_realloc(struct _malloc_zone_t* zone, |
333 void* ptr, | 339 void* ptr, |
334 size_t size) { | 340 size_t size) { |
335 #if ARCH_CPU_32_BITS | 341 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
336 ScopedClearErrno clear_errno; | 342 ScopedClearErrno clear_errno; |
337 #endif // ARCH_CPU_32_BITS | 343 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
338 void* result = g_old_realloc(zone, ptr, size); | 344 void* result = g_old_realloc(zone, ptr, size); |
339 if (!result && size) | 345 if (!result && size) |
340 debug::BreakDebugger(); | 346 debug::BreakDebugger(); |
341 return result; | 347 return result; |
342 } | 348 } |
343 | 349 |
344 void* oom_killer_memalign(struct _malloc_zone_t* zone, | 350 void* oom_killer_memalign(struct _malloc_zone_t* zone, |
345 size_t alignment, | 351 size_t alignment, |
346 size_t size) { | 352 size_t size) { |
347 #if ARCH_CPU_32_BITS | 353 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
348 ScopedClearErrno clear_errno; | 354 ScopedClearErrno clear_errno; |
349 #endif // ARCH_CPU_32_BITS | 355 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
350 void* result = g_old_memalign(zone, alignment, size); | 356 void* result = g_old_memalign(zone, alignment, size); |
351 // Only die if posix_memalign would have returned ENOMEM, since there are | 357 // Only die if posix_memalign would have returned ENOMEM, since there are |
352 // other reasons why NULL might be returned (see | 358 // other reasons why NULL might be returned (see |
353 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 359 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
354 if (!result && size && alignment >= sizeof(void*) | 360 if (!result && size && alignment >= sizeof(void*) |
355 && (alignment & (alignment - 1)) == 0) { | 361 && (alignment & (alignment - 1)) == 0) { |
356 debug::BreakDebugger(); | 362 debug::BreakDebugger(); |
357 } | 363 } |
358 return result; | 364 return result; |
359 } | 365 } |
360 | 366 |
361 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, | 367 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, |
362 size_t size) { | 368 size_t size) { |
363 #if ARCH_CPU_32_BITS | 369 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
364 ScopedClearErrno clear_errno; | 370 ScopedClearErrno clear_errno; |
365 #endif // ARCH_CPU_32_BITS | 371 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
366 void* result = g_old_malloc_purgeable(zone, size); | 372 void* result = g_old_malloc_purgeable(zone, size); |
367 if (!result && size) | 373 if (!result && size) |
368 debug::BreakDebugger(); | 374 debug::BreakDebugger(); |
369 return result; | 375 return result; |
370 } | 376 } |
371 | 377 |
372 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, | 378 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, |
373 size_t num_items, | 379 size_t num_items, |
374 size_t size) { | 380 size_t size) { |
375 #if ARCH_CPU_32_BITS | 381 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
376 ScopedClearErrno clear_errno; | 382 ScopedClearErrno clear_errno; |
377 #endif // ARCH_CPU_32_BITS | 383 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
378 void* result = g_old_calloc_purgeable(zone, num_items, size); | 384 void* result = g_old_calloc_purgeable(zone, num_items, size); |
379 if (!result && num_items && size) | 385 if (!result && num_items && size) |
380 debug::BreakDebugger(); | 386 debug::BreakDebugger(); |
381 return result; | 387 return result; |
382 } | 388 } |
383 | 389 |
384 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, | 390 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, |
385 size_t size) { | 391 size_t size) { |
386 #if ARCH_CPU_32_BITS | 392 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
387 ScopedClearErrno clear_errno; | 393 ScopedClearErrno clear_errno; |
388 #endif // ARCH_CPU_32_BITS | 394 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
389 void* result = g_old_valloc_purgeable(zone, size); | 395 void* result = g_old_valloc_purgeable(zone, size); |
390 if (!result && size) | 396 if (!result && size) |
391 debug::BreakDebugger(); | 397 debug::BreakDebugger(); |
392 return result; | 398 return result; |
393 } | 399 } |
394 | 400 |
395 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, | 401 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, |
396 void* ptr) { | 402 void* ptr) { |
397 #if ARCH_CPU_32_BITS | 403 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
398 ScopedClearErrno clear_errno; | 404 ScopedClearErrno clear_errno; |
399 #endif // ARCH_CPU_32_BITS | 405 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
400 g_old_free_purgeable(zone, ptr); | 406 g_old_free_purgeable(zone, ptr); |
401 } | 407 } |
402 | 408 |
403 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, | 409 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, |
404 void* ptr, | 410 void* ptr, |
405 size_t size) { | 411 size_t size) { |
406 #if ARCH_CPU_32_BITS | 412 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
407 ScopedClearErrno clear_errno; | 413 ScopedClearErrno clear_errno; |
408 #endif // ARCH_CPU_32_BITS | 414 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
409 void* result = g_old_realloc_purgeable(zone, ptr, size); | 415 void* result = g_old_realloc_purgeable(zone, ptr, size); |
410 if (!result && size) | 416 if (!result && size) |
411 debug::BreakDebugger(); | 417 debug::BreakDebugger(); |
412 return result; | 418 return result; |
413 } | 419 } |
414 | 420 |
415 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, | 421 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, |
416 size_t alignment, | 422 size_t alignment, |
417 size_t size) { | 423 size_t size) { |
418 #if ARCH_CPU_32_BITS | 424 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
419 ScopedClearErrno clear_errno; | 425 ScopedClearErrno clear_errno; |
420 #endif // ARCH_CPU_32_BITS | 426 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
421 void* result = g_old_memalign_purgeable(zone, alignment, size); | 427 void* result = g_old_memalign_purgeable(zone, alignment, size); |
422 // Only die if posix_memalign would have returned ENOMEM, since there are | 428 // Only die if posix_memalign would have returned ENOMEM, since there are |
423 // other reasons why NULL might be returned (see | 429 // other reasons why NULL might be returned (see |
424 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 430 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
425 if (!result && size && alignment >= sizeof(void*) | 431 if (!result && size && alignment >= sizeof(void*) |
426 && (alignment & (alignment - 1)) == 0) { | 432 && (alignment & (alignment - 1)) == 0) { |
427 debug::BreakDebugger(); | 433 debug::BreakDebugger(); |
428 } | 434 } |
429 return result; | 435 return result; |
430 } | 436 } |
431 | 437 |
438 #endif // !defined(ADDRESS_SANITIZER) | |
439 | |
432 // === C++ operator new === | 440 // === C++ operator new === |
433 | 441 |
434 void oom_killer_new() { | 442 void oom_killer_new() { |
435 debug::BreakDebugger(); | 443 debug::BreakDebugger(); |
436 } | 444 } |
437 | 445 |
446 #if !defined(ADDRESS_SANITIZER) | |
447 | |
438 // === Core Foundation CFAllocators === | 448 // === Core Foundation CFAllocators === |
439 | 449 |
440 bool CanGetContextForCFAllocator() { | 450 bool CanGetContextForCFAllocator() { |
441 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); | 451 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); |
442 } | 452 } |
443 | 453 |
444 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { | 454 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { |
445 if (base::mac::IsOSSnowLeopard()) { | 455 if (base::mac::IsOSSnowLeopard()) { |
446 ChromeCFAllocatorLeopards* our_allocator = | 456 ChromeCFAllocatorLeopards* our_allocator = |
447 const_cast<ChromeCFAllocatorLeopards*>( | 457 const_cast<ChromeCFAllocatorLeopards*>( |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
484 | 494 |
485 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, | 495 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, |
486 CFOptionFlags hint, | 496 CFOptionFlags hint, |
487 void* info) { | 497 void* info) { |
488 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); | 498 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); |
489 if (!result) | 499 if (!result) |
490 debug::BreakDebugger(); | 500 debug::BreakDebugger(); |
491 return result; | 501 return result; |
492 } | 502 } |
493 | 503 |
504 #endif // !defined(ADDRESS_SANITIZER) | |
505 | |
494 // === Cocoa NSObject allocation === | 506 // === Cocoa NSObject allocation === |
495 | 507 |
496 typedef id (*allocWithZone_t)(id, SEL, NSZone*); | 508 typedef id (*allocWithZone_t)(id, SEL, NSZone*); |
497 allocWithZone_t g_old_allocWithZone; | 509 allocWithZone_t g_old_allocWithZone; |
498 | 510 |
499 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) | 511 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) |
500 { | 512 { |
501 id result = g_old_allocWithZone(self, _cmd, zone); | 513 id result = g_old_allocWithZone(self, _cmd, zone); |
502 if (!result) | 514 if (!result) |
503 debug::BreakDebugger(); | 515 debug::BreakDebugger(); |
504 return result; | 516 return result; |
505 } | 517 } |
506 | 518 |
507 } // namespace | 519 } // namespace |
508 | 520 |
509 bool UncheckedMalloc(size_t size, void** result) { | 521 bool UncheckedMalloc(size_t size, void** result) { |
522 | |
523 #if !defined(ADDRESS_SANITIZER) | |
Scott Hess - ex-Googler
2014/07/16 19:53:47
I'd invert this and put the ASAN case closer to th
tzik
2014/07/17 08:17:27
Done.
| |
510 if (g_old_malloc) { | 524 if (g_old_malloc) { |
511 #if ARCH_CPU_32_BITS | 525 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
512 ScopedClearErrno clear_errno; | 526 ScopedClearErrno clear_errno; |
513 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); | 527 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); |
514 #endif // ARCH_CPU_32_BITS | 528 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
515 *result = g_old_malloc(malloc_default_zone(), size); | 529 *result = g_old_malloc(malloc_default_zone(), size); |
516 } else { | 530 } else { |
517 *result = malloc(size); | 531 *result = malloc(size); |
518 } | 532 } |
533 #else | |
534 *result = malloc(size); | |
535 #endif // !defined(ADDRESS_SANITIZER) | |
519 | 536 |
520 return *result != NULL; | 537 return *result != NULL; |
521 } | 538 } |
522 | 539 |
523 bool UncheckedCalloc(size_t num_items, size_t size, void** result) { | 540 bool UncheckedCalloc(size_t num_items, size_t size, void** result) { |
524 if (g_old_calloc) { | 541 if (g_old_calloc) { |
525 #if ARCH_CPU_32_BITS | 542 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
526 ScopedClearErrno clear_errno; | 543 ScopedClearErrno clear_errno; |
527 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); | 544 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); |
528 #endif // ARCH_CPU_32_BITS | 545 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
529 *result = g_old_calloc(malloc_default_zone(), num_items, size); | 546 *result = g_old_calloc(malloc_default_zone(), num_items, size); |
530 } else { | 547 } else { |
531 *result = calloc(num_items, size); | 548 *result = calloc(num_items, size); |
532 } | 549 } |
533 | 550 |
534 return *result != NULL; | 551 return *result != NULL; |
535 } | 552 } |
536 | 553 |
537 void* UncheckedMalloc(size_t size) { | 554 void* UncheckedMalloc(size_t size) { |
538 void* address; | 555 void* address; |
(...skipping 13 matching lines...) Expand all Loading... | |
552 | 569 |
553 // === C malloc/calloc/valloc/realloc/posix_memalign === | 570 // === C malloc/calloc/valloc/realloc/posix_memalign === |
554 | 571 |
555 // This approach is not perfect, as requests for amounts of memory larger than | 572 // This approach is not perfect, as requests for amounts of memory larger than |
556 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will | 573 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will |
557 // still fail with a NULL rather than dying (see | 574 // still fail with a NULL rather than dying (see |
558 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). | 575 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). |
559 // Unfortunately, it's the best we can do. Also note that this does not affect | 576 // Unfortunately, it's the best we can do. Also note that this does not affect |
560 // allocations from non-default zones. | 577 // allocations from non-default zones. |
561 | 578 |
579 #if !defined(ADDRESS_SANITIZER) | |
580 // Don't do anything special on OOM for the malloc zones replaced by | |
581 // AddressSanitizer, as modifying or protecting them may not work correctly. | |
582 | |
562 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && | 583 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && |
563 !g_old_memalign) << "Old allocators unexpectedly non-null"; | 584 !g_old_memalign) << "Old allocators unexpectedly non-null"; |
564 | 585 |
565 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && | 586 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && |
566 !g_old_valloc_purgeable && !g_old_realloc_purgeable && | 587 !g_old_valloc_purgeable && !g_old_realloc_purgeable && |
567 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; | 588 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; |
568 | 589 |
569 #if !defined(ADDRESS_SANITIZER) | |
570 // Don't do anything special on OOM for the malloc zones replaced by | |
571 // AddressSanitizer, as modifying or protecting them may not work correctly. | |
572 | |
573 ChromeMallocZone* default_zone = | 590 ChromeMallocZone* default_zone = |
574 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); | 591 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
575 ChromeMallocZone* purgeable_zone = | 592 ChromeMallocZone* purgeable_zone = |
576 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); | 593 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
577 | 594 |
578 mach_vm_address_t default_reprotection_start = 0; | 595 mach_vm_address_t default_reprotection_start = 0; |
579 mach_vm_size_t default_reprotection_length = 0; | 596 mach_vm_size_t default_reprotection_length = 0; |
580 vm_prot_t default_reprotection_value = VM_PROT_NONE; | 597 vm_prot_t default_reprotection_value = VM_PROT_NONE; |
581 DeprotectMallocZone(default_zone, | 598 DeprotectMallocZone(default_zone, |
582 &default_reprotection_start, | 599 &default_reprotection_start, |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 @selector(allocWithZone:)); | 759 @selector(allocWithZone:)); |
743 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( | 760 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( |
744 method_getImplementation(orig_method)); | 761 method_getImplementation(orig_method)); |
745 CHECK(g_old_allocWithZone) | 762 CHECK(g_old_allocWithZone) |
746 << "Failed to get allocWithZone allocation function."; | 763 << "Failed to get allocWithZone allocation function."; |
747 method_setImplementation(orig_method, | 764 method_setImplementation(orig_method, |
748 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 765 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
749 } | 766 } |
750 | 767 |
751 } // namespace base | 768 } // namespace base |
OLD | NEW |