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) |
169 // AddressSanitizer handles heap corruption, and on 64 bit Macs, the malloc | |
170 // system automatically abort()s on heap corruption. | |
171 return; | |
172 #else | |
173 // Only override once, otherwise CrMallocErrorBreak() will recurse | 175 // Only override once, otherwise CrMallocErrorBreak() will recurse |
174 // to itself. | 176 // to itself. |
175 if (g_original_malloc_error_break) | 177 if (g_original_malloc_error_break) |
176 return; | 178 return; |
177 | 179 |
178 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); | 180 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); |
179 if (!malloc_error_break) { | 181 if (!malloc_error_break) { |
180 DLOG(WARNING) << "Could not find malloc_error_break"; | 182 DLOG(WARNING) << "Could not find malloc_error_break"; |
181 return; | 183 return; |
182 } | 184 } |
183 | 185 |
184 mach_error_t err = mach_override_ptr( | 186 mach_error_t err = mach_override_ptr( |
185 (void*)malloc_error_break, | 187 (void*)malloc_error_break, |
186 (void*)&CrMallocErrorBreak, | 188 (void*)&CrMallocErrorBreak, |
187 (void**)&g_original_malloc_error_break); | 189 (void**)&g_original_malloc_error_break); |
188 | 190 |
189 if (err != err_none) | 191 if (err != err_none) |
190 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; | 192 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; |
191 #endif // defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS | 193 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
192 } | 194 } |
193 | 195 |
194 // ------------------------------------------------------------------------ | 196 // ------------------------------------------------------------------------ |
195 | 197 |
196 namespace { | 198 namespace { |
197 | 199 |
198 bool g_oom_killer_enabled; | 200 bool g_oom_killer_enabled; |
199 | 201 |
| 202 #if !defined(ADDRESS_SANITIZER) |
| 203 |
200 // Starting with Mac OS X 10.7, the zone allocators set up by the system are | 204 // 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, | 205 // read-only, to prevent them from being overwritten in an attack. However, |
202 // blindly unprotecting and reprotecting the zone allocators fails with | 206 // blindly unprotecting and reprotecting the zone allocators fails with |
203 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of | 207 // 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. | 208 // memory in its bss. Explicit saving/restoring of the protection is required. |
205 // | 209 // |
206 // This function takes a pointer to a malloc zone, de-protects it if necessary, | 210 // 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 | 211 // 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 | 212 // re-protected when modifications are complete. This approach assumes that |
209 // there is no contention for the protection of this memory. | 213 // there is no contention for the protection of this memory. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 | 286 |
283 malloc_type g_old_malloc_purgeable; | 287 malloc_type g_old_malloc_purgeable; |
284 calloc_type g_old_calloc_purgeable; | 288 calloc_type g_old_calloc_purgeable; |
285 valloc_type g_old_valloc_purgeable; | 289 valloc_type g_old_valloc_purgeable; |
286 free_type g_old_free_purgeable; | 290 free_type g_old_free_purgeable; |
287 realloc_type g_old_realloc_purgeable; | 291 realloc_type g_old_realloc_purgeable; |
288 memalign_type g_old_memalign_purgeable; | 292 memalign_type g_old_memalign_purgeable; |
289 | 293 |
290 void* oom_killer_malloc(struct _malloc_zone_t* zone, | 294 void* oom_killer_malloc(struct _malloc_zone_t* zone, |
291 size_t size) { | 295 size_t size) { |
292 #if ARCH_CPU_32_BITS | 296 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
293 ScopedClearErrno clear_errno; | 297 ScopedClearErrno clear_errno; |
294 #endif // ARCH_CPU_32_BITS | 298 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
295 void* result = g_old_malloc(zone, size); | 299 void* result = g_old_malloc(zone, size); |
296 if (!result && size) | 300 if (!result && size) |
297 debug::BreakDebugger(); | 301 debug::BreakDebugger(); |
298 return result; | 302 return result; |
299 } | 303 } |
300 | 304 |
301 void* oom_killer_calloc(struct _malloc_zone_t* zone, | 305 void* oom_killer_calloc(struct _malloc_zone_t* zone, |
302 size_t num_items, | 306 size_t num_items, |
303 size_t size) { | 307 size_t size) { |
304 #if ARCH_CPU_32_BITS | 308 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
305 ScopedClearErrno clear_errno; | 309 ScopedClearErrno clear_errno; |
306 #endif // ARCH_CPU_32_BITS | 310 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
307 void* result = g_old_calloc(zone, num_items, size); | 311 void* result = g_old_calloc(zone, num_items, size); |
308 if (!result && num_items && size) | 312 if (!result && num_items && size) |
309 debug::BreakDebugger(); | 313 debug::BreakDebugger(); |
310 return result; | 314 return result; |
311 } | 315 } |
312 | 316 |
313 void* oom_killer_valloc(struct _malloc_zone_t* zone, | 317 void* oom_killer_valloc(struct _malloc_zone_t* zone, |
314 size_t size) { | 318 size_t size) { |
315 #if ARCH_CPU_32_BITS | 319 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
316 ScopedClearErrno clear_errno; | 320 ScopedClearErrno clear_errno; |
317 #endif // ARCH_CPU_32_BITS | 321 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
318 void* result = g_old_valloc(zone, size); | 322 void* result = g_old_valloc(zone, size); |
319 if (!result && size) | 323 if (!result && size) |
320 debug::BreakDebugger(); | 324 debug::BreakDebugger(); |
321 return result; | 325 return result; |
322 } | 326 } |
323 | 327 |
324 void oom_killer_free(struct _malloc_zone_t* zone, | 328 void oom_killer_free(struct _malloc_zone_t* zone, |
325 void* ptr) { | 329 void* ptr) { |
326 #if ARCH_CPU_32_BITS | 330 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
327 ScopedClearErrno clear_errno; | 331 ScopedClearErrno clear_errno; |
328 #endif // ARCH_CPU_32_BITS | 332 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
329 g_old_free(zone, ptr); | 333 g_old_free(zone, ptr); |
330 } | 334 } |
331 | 335 |
332 void* oom_killer_realloc(struct _malloc_zone_t* zone, | 336 void* oom_killer_realloc(struct _malloc_zone_t* zone, |
333 void* ptr, | 337 void* ptr, |
334 size_t size) { | 338 size_t size) { |
335 #if ARCH_CPU_32_BITS | 339 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
336 ScopedClearErrno clear_errno; | 340 ScopedClearErrno clear_errno; |
337 #endif // ARCH_CPU_32_BITS | 341 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
338 void* result = g_old_realloc(zone, ptr, size); | 342 void* result = g_old_realloc(zone, ptr, size); |
339 if (!result && size) | 343 if (!result && size) |
340 debug::BreakDebugger(); | 344 debug::BreakDebugger(); |
341 return result; | 345 return result; |
342 } | 346 } |
343 | 347 |
344 void* oom_killer_memalign(struct _malloc_zone_t* zone, | 348 void* oom_killer_memalign(struct _malloc_zone_t* zone, |
345 size_t alignment, | 349 size_t alignment, |
346 size_t size) { | 350 size_t size) { |
347 #if ARCH_CPU_32_BITS | 351 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
348 ScopedClearErrno clear_errno; | 352 ScopedClearErrno clear_errno; |
349 #endif // ARCH_CPU_32_BITS | 353 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
350 void* result = g_old_memalign(zone, alignment, size); | 354 void* result = g_old_memalign(zone, alignment, size); |
351 // Only die if posix_memalign would have returned ENOMEM, since there are | 355 // Only die if posix_memalign would have returned ENOMEM, since there are |
352 // other reasons why NULL might be returned (see | 356 // other reasons why NULL might be returned (see |
353 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 357 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
354 if (!result && size && alignment >= sizeof(void*) | 358 if (!result && size && alignment >= sizeof(void*) |
355 && (alignment & (alignment - 1)) == 0) { | 359 && (alignment & (alignment - 1)) == 0) { |
356 debug::BreakDebugger(); | 360 debug::BreakDebugger(); |
357 } | 361 } |
358 return result; | 362 return result; |
359 } | 363 } |
360 | 364 |
361 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, | 365 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, |
362 size_t size) { | 366 size_t size) { |
363 #if ARCH_CPU_32_BITS | 367 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
364 ScopedClearErrno clear_errno; | 368 ScopedClearErrno clear_errno; |
365 #endif // ARCH_CPU_32_BITS | 369 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
366 void* result = g_old_malloc_purgeable(zone, size); | 370 void* result = g_old_malloc_purgeable(zone, size); |
367 if (!result && size) | 371 if (!result && size) |
368 debug::BreakDebugger(); | 372 debug::BreakDebugger(); |
369 return result; | 373 return result; |
370 } | 374 } |
371 | 375 |
372 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, | 376 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, |
373 size_t num_items, | 377 size_t num_items, |
374 size_t size) { | 378 size_t size) { |
375 #if ARCH_CPU_32_BITS | 379 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
376 ScopedClearErrno clear_errno; | 380 ScopedClearErrno clear_errno; |
377 #endif // ARCH_CPU_32_BITS | 381 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
378 void* result = g_old_calloc_purgeable(zone, num_items, size); | 382 void* result = g_old_calloc_purgeable(zone, num_items, size); |
379 if (!result && num_items && size) | 383 if (!result && num_items && size) |
380 debug::BreakDebugger(); | 384 debug::BreakDebugger(); |
381 return result; | 385 return result; |
382 } | 386 } |
383 | 387 |
384 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, | 388 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, |
385 size_t size) { | 389 size_t size) { |
386 #if ARCH_CPU_32_BITS | 390 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
387 ScopedClearErrno clear_errno; | 391 ScopedClearErrno clear_errno; |
388 #endif // ARCH_CPU_32_BITS | 392 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
389 void* result = g_old_valloc_purgeable(zone, size); | 393 void* result = g_old_valloc_purgeable(zone, size); |
390 if (!result && size) | 394 if (!result && size) |
391 debug::BreakDebugger(); | 395 debug::BreakDebugger(); |
392 return result; | 396 return result; |
393 } | 397 } |
394 | 398 |
395 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, | 399 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, |
396 void* ptr) { | 400 void* ptr) { |
397 #if ARCH_CPU_32_BITS | 401 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
398 ScopedClearErrno clear_errno; | 402 ScopedClearErrno clear_errno; |
399 #endif // ARCH_CPU_32_BITS | 403 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
400 g_old_free_purgeable(zone, ptr); | 404 g_old_free_purgeable(zone, ptr); |
401 } | 405 } |
402 | 406 |
403 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, | 407 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, |
404 void* ptr, | 408 void* ptr, |
405 size_t size) { | 409 size_t size) { |
406 #if ARCH_CPU_32_BITS | 410 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
407 ScopedClearErrno clear_errno; | 411 ScopedClearErrno clear_errno; |
408 #endif // ARCH_CPU_32_BITS | 412 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
409 void* result = g_old_realloc_purgeable(zone, ptr, size); | 413 void* result = g_old_realloc_purgeable(zone, ptr, size); |
410 if (!result && size) | 414 if (!result && size) |
411 debug::BreakDebugger(); | 415 debug::BreakDebugger(); |
412 return result; | 416 return result; |
413 } | 417 } |
414 | 418 |
415 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, | 419 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, |
416 size_t alignment, | 420 size_t alignment, |
417 size_t size) { | 421 size_t size) { |
418 #if ARCH_CPU_32_BITS | 422 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
419 ScopedClearErrno clear_errno; | 423 ScopedClearErrno clear_errno; |
420 #endif // ARCH_CPU_32_BITS | 424 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
421 void* result = g_old_memalign_purgeable(zone, alignment, size); | 425 void* result = g_old_memalign_purgeable(zone, alignment, size); |
422 // Only die if posix_memalign would have returned ENOMEM, since there are | 426 // Only die if posix_memalign would have returned ENOMEM, since there are |
423 // other reasons why NULL might be returned (see | 427 // other reasons why NULL might be returned (see |
424 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 428 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
425 if (!result && size && alignment >= sizeof(void*) | 429 if (!result && size && alignment >= sizeof(void*) |
426 && (alignment & (alignment - 1)) == 0) { | 430 && (alignment & (alignment - 1)) == 0) { |
427 debug::BreakDebugger(); | 431 debug::BreakDebugger(); |
428 } | 432 } |
429 return result; | 433 return result; |
430 } | 434 } |
431 | 435 |
| 436 #endif // !defined(ADDRESS_SANITIZER) |
| 437 |
432 // === C++ operator new === | 438 // === C++ operator new === |
433 | 439 |
434 void oom_killer_new() { | 440 void oom_killer_new() { |
435 debug::BreakDebugger(); | 441 debug::BreakDebugger(); |
436 } | 442 } |
437 | 443 |
| 444 #if !defined(ADDRESS_SANITIZER) |
| 445 |
438 // === Core Foundation CFAllocators === | 446 // === Core Foundation CFAllocators === |
439 | 447 |
440 bool CanGetContextForCFAllocator() { | 448 bool CanGetContextForCFAllocator() { |
441 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); | 449 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); |
442 } | 450 } |
443 | 451 |
444 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { | 452 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { |
445 if (base::mac::IsOSSnowLeopard()) { | 453 if (base::mac::IsOSSnowLeopard()) { |
446 ChromeCFAllocatorLeopards* our_allocator = | 454 ChromeCFAllocatorLeopards* our_allocator = |
447 const_cast<ChromeCFAllocatorLeopards*>( | 455 const_cast<ChromeCFAllocatorLeopards*>( |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 | 492 |
485 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, | 493 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, |
486 CFOptionFlags hint, | 494 CFOptionFlags hint, |
487 void* info) { | 495 void* info) { |
488 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); | 496 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); |
489 if (!result) | 497 if (!result) |
490 debug::BreakDebugger(); | 498 debug::BreakDebugger(); |
491 return result; | 499 return result; |
492 } | 500 } |
493 | 501 |
| 502 #endif // !defined(ADDRESS_SANITIZER) |
| 503 |
494 // === Cocoa NSObject allocation === | 504 // === Cocoa NSObject allocation === |
495 | 505 |
496 typedef id (*allocWithZone_t)(id, SEL, NSZone*); | 506 typedef id (*allocWithZone_t)(id, SEL, NSZone*); |
497 allocWithZone_t g_old_allocWithZone; | 507 allocWithZone_t g_old_allocWithZone; |
498 | 508 |
499 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) | 509 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) |
500 { | 510 { |
501 id result = g_old_allocWithZone(self, _cmd, zone); | 511 id result = g_old_allocWithZone(self, _cmd, zone); |
502 if (!result) | 512 if (!result) |
503 debug::BreakDebugger(); | 513 debug::BreakDebugger(); |
504 return result; | 514 return result; |
505 } | 515 } |
506 | 516 |
507 } // namespace | 517 } // namespace |
508 | 518 |
509 bool UncheckedMalloc(size_t size, void** result) { | 519 bool UncheckedMalloc(size_t size, void** result) { |
| 520 #if defined(ADDRESS_SANITIZER) |
| 521 *result = malloc(size); |
| 522 #else |
510 if (g_old_malloc) { | 523 if (g_old_malloc) { |
511 #if ARCH_CPU_32_BITS | 524 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
512 ScopedClearErrno clear_errno; | 525 ScopedClearErrno clear_errno; |
513 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); | 526 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); |
514 #endif // ARCH_CPU_32_BITS | 527 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
515 *result = g_old_malloc(malloc_default_zone(), size); | 528 *result = g_old_malloc(malloc_default_zone(), size); |
516 } else { | 529 } else { |
517 *result = malloc(size); | 530 *result = malloc(size); |
518 } | 531 } |
| 532 #endif // defined(ADDRESS_SANITIZER) |
519 | 533 |
520 return *result != NULL; | 534 return *result != NULL; |
521 } | 535 } |
522 | 536 |
523 bool UncheckedCalloc(size_t num_items, size_t size, void** result) { | 537 bool UncheckedCalloc(size_t num_items, size_t size, void** result) { |
| 538 #if defined(ADDRESS_SANITIZER) |
| 539 *result = calloc(num_items, size); |
| 540 #else |
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 } |
| 550 #endif // defined(ADDRESS_SANITIZER) |
533 | 551 |
534 return *result != NULL; | 552 return *result != NULL; |
535 } | 553 } |
536 | 554 |
537 void* UncheckedMalloc(size_t size) { | 555 void* UncheckedMalloc(size_t size) { |
538 void* address; | 556 void* address; |
539 return UncheckedMalloc(size, &address) ? address : NULL; | 557 return UncheckedMalloc(size, &address) ? address : NULL; |
540 } | 558 } |
541 | 559 |
542 void* UncheckedCalloc(size_t num_items, size_t size) { | 560 void* UncheckedCalloc(size_t num_items, size_t size) { |
543 void* address; | 561 void* address; |
544 return UncheckedCalloc(num_items, size, &address) ? address : NULL; | 562 return UncheckedCalloc(num_items, size, &address) ? address : NULL; |
545 } | 563 } |
546 | 564 |
547 void EnableTerminationOnOutOfMemory() { | 565 void EnableTerminationOnOutOfMemory() { |
548 if (g_oom_killer_enabled) | 566 if (g_oom_killer_enabled) |
549 return; | 567 return; |
550 | 568 |
551 g_oom_killer_enabled = true; | 569 g_oom_killer_enabled = true; |
552 | 570 |
553 // === C malloc/calloc/valloc/realloc/posix_memalign === | 571 // === C malloc/calloc/valloc/realloc/posix_memalign === |
554 | 572 |
555 // This approach is not perfect, as requests for amounts of memory larger than | 573 // 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 | 574 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will |
557 // still fail with a NULL rather than dying (see | 575 // still fail with a NULL rather than dying (see |
558 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). | 576 // 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 | 577 // Unfortunately, it's the best we can do. Also note that this does not affect |
560 // allocations from non-default zones. | 578 // allocations from non-default zones. |
561 | 579 |
| 580 #if !defined(ADDRESS_SANITIZER) |
| 581 // Don't do anything special on OOM for the malloc zones replaced by |
| 582 // AddressSanitizer, as modifying or protecting them may not work correctly. |
| 583 |
562 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && | 584 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && |
563 !g_old_memalign) << "Old allocators unexpectedly non-null"; | 585 !g_old_memalign) << "Old allocators unexpectedly non-null"; |
564 | 586 |
565 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && | 587 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && |
566 !g_old_valloc_purgeable && !g_old_realloc_purgeable && | 588 !g_old_valloc_purgeable && !g_old_realloc_purgeable && |
567 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; | 589 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; |
568 | 590 |
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 = | 591 ChromeMallocZone* default_zone = |
574 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); | 592 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
575 ChromeMallocZone* purgeable_zone = | 593 ChromeMallocZone* purgeable_zone = |
576 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); | 594 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
577 | 595 |
578 mach_vm_address_t default_reprotection_start = 0; | 596 mach_vm_address_t default_reprotection_start = 0; |
579 mach_vm_size_t default_reprotection_length = 0; | 597 mach_vm_size_t default_reprotection_length = 0; |
580 vm_prot_t default_reprotection_value = VM_PROT_NONE; | 598 vm_prot_t default_reprotection_value = VM_PROT_NONE; |
581 DeprotectMallocZone(default_zone, | 599 DeprotectMallocZone(default_zone, |
582 &default_reprotection_start, | 600 &default_reprotection_start, |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 @selector(allocWithZone:)); | 760 @selector(allocWithZone:)); |
743 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( | 761 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( |
744 method_getImplementation(orig_method)); | 762 method_getImplementation(orig_method)); |
745 CHECK(g_old_allocWithZone) | 763 CHECK(g_old_allocWithZone) |
746 << "Failed to get allocWithZone allocation function."; | 764 << "Failed to get allocWithZone allocation function."; |
747 method_setImplementation(orig_method, | 765 method_setImplementation(orig_method, |
748 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 766 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
749 } | 767 } |
750 | 768 |
751 } // namespace base | 769 } // namespace base |
OLD | NEW |