| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 WTF_EXPORT void partitionPurgeMemory(PartitionRoot*, int); | 404 WTF_EXPORT void partitionPurgeMemory(PartitionRoot*, int); |
| 405 WTF_EXPORT void partitionPurgeMemoryGeneric(PartitionRootGeneric*, int); | 405 WTF_EXPORT void partitionPurgeMemoryGeneric(PartitionRootGeneric*, int); |
| 406 | 406 |
| 407 WTF_EXPORT NEVER_INLINE void* partitionAllocSlowPath(PartitionRootBase*, int, si
ze_t, PartitionBucket*); | 407 WTF_EXPORT NEVER_INLINE void* partitionAllocSlowPath(PartitionRootBase*, int, si
ze_t, PartitionBucket*); |
| 408 WTF_EXPORT NEVER_INLINE void partitionFreeSlowPath(PartitionPage*); | 408 WTF_EXPORT NEVER_INLINE void partitionFreeSlowPath(PartitionPage*); |
| 409 WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, voi
d*, size_t); | 409 WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, voi
d*, size_t); |
| 410 | 410 |
| 411 WTF_EXPORT void partitionDumpStats(PartitionRoot*, const char* partitionName, bo
ol isLightDump, PartitionStatsDumper*); | 411 WTF_EXPORT void partitionDumpStats(PartitionRoot*, const char* partitionName, bo
ol isLightDump, PartitionStatsDumper*); |
| 412 WTF_EXPORT void partitionDumpStatsGeneric(PartitionRootGeneric*, const char* par
titionName, bool isLightDump, PartitionStatsDumper*); | 412 WTF_EXPORT void partitionDumpStatsGeneric(PartitionRootGeneric*, const char* par
titionName, bool isLightDump, PartitionStatsDumper*); |
| 413 | 413 |
| 414 class WTF_EXPORT PartitionAllocHooks { |
| 415 public: |
| 416 typedef void AllocationHook(void* address, size_t); |
| 417 typedef void FreeHook(void* address); |
| 418 |
| 419 static void setAllocationHook(AllocationHook* hook) { m_allocationHook = hoo
k; } |
| 420 static void setFreeHook(FreeHook* hook) { m_freeHook = hook; } |
| 421 |
| 422 static void maybeInvokeAllocationHook(void* address, size_t size) |
| 423 { |
| 424 AllocationHook* hook = m_allocationHook; |
| 425 if (UNLIKELY(hook != nullptr)) |
| 426 hook(address, size); |
| 427 } |
| 428 |
| 429 static void maybeInvokeFreeHook(void* address) |
| 430 { |
| 431 FreeHook* hook = m_freeHook; |
| 432 if (UNLIKELY(hook != nullptr)) |
| 433 hook(address); |
| 434 } |
| 435 |
| 436 static void maybeInvokeReallocationHook(void* oldAddress, void* newAddress,
size_t size) |
| 437 { |
| 438 // Report a reallocation as a free followed by an allocation. |
| 439 AllocationHook* allocHook = m_allocationHook; |
| 440 FreeHook* freeHook = m_freeHook; |
| 441 if (UNLIKELY(allocHook && freeHook)) { |
| 442 freeHook(oldAddress); |
| 443 allocHook(newAddress, size); |
| 444 } |
| 445 } |
| 446 |
| 447 private: |
| 448 // Pointers to hook functions that PartitionAlloc will call on allocation an
d |
| 449 // free if the pointers are non-null. |
| 450 static AllocationHook* m_allocationHook; |
| 451 static FreeHook* m_freeHook; |
| 452 }; |
| 453 |
| 414 ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEnt
ry* ptr) | 454 ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEnt
ry* ptr) |
| 415 { | 455 { |
| 416 // We use bswap on little endian as a fast mask for two reasons: | 456 // We use bswap on little endian as a fast mask for two reasons: |
| 417 // 1) If an object is freed and its vtable used where the attacker doesn't | 457 // 1) If an object is freed and its vtable used where the attacker doesn't |
| 418 // get the chance to run allocations between the free and use, the vtable | 458 // get the chance to run allocations between the free and use, the vtable |
| 419 // dereference is likely to fault. | 459 // dereference is likely to fault. |
| 420 // 2) If the attacker has a linear buffer overflow and elects to try and | 460 // 2) If the attacker has a linear buffer overflow and elects to try and |
| 421 // corrupt a freelist pointer, partial pointer overwrite attacks are | 461 // corrupt a freelist pointer, partial pointer overwrite attacks are |
| 422 // thwarted. | 462 // thwarted. |
| 423 // For big endian, similar guarantees are arrived at with a negation. | 463 // For big endian, similar guarantees are arrived at with a negation. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 slotSize = rawSize; | 646 slotSize = rawSize; |
| 607 } | 647 } |
| 608 size_t noCookieSize = partitionCookieSizeAdjustSubtract(slotSize); | 648 size_t noCookieSize = partitionCookieSizeAdjustSubtract(slotSize); |
| 609 char* charRet = static_cast<char*>(ret); | 649 char* charRet = static_cast<char*>(ret); |
| 610 // The value given to the application is actually just after the cookie. | 650 // The value given to the application is actually just after the cookie. |
| 611 ret = charRet + kCookieSize; | 651 ret = charRet + kCookieSize; |
| 612 memset(ret, kUninitializedByte, noCookieSize); | 652 memset(ret, kUninitializedByte, noCookieSize); |
| 613 partitionCookieWriteValue(charRet); | 653 partitionCookieWriteValue(charRet); |
| 614 partitionCookieWriteValue(charRet + kCookieSize + noCookieSize); | 654 partitionCookieWriteValue(charRet + kCookieSize + noCookieSize); |
| 615 #endif | 655 #endif |
| 656 |
| 657 PartitionAllocHooks::maybeInvokeAllocationHook(ret, size); |
| 658 |
| 616 return ret; | 659 return ret; |
| 617 } | 660 } |
| 618 | 661 |
| 619 ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size) | 662 ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size) |
| 620 { | 663 { |
| 621 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 664 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
| 622 void* result = malloc(size); | 665 void* result = malloc(size); |
| 623 RELEASE_ASSERT(result); | 666 RELEASE_ASSERT(result); |
| 624 return result; | 667 return result; |
| 625 #else | 668 #else |
| (...skipping 12 matching lines...) Expand all Loading... |
| 638 // If these asserts fire, you probably corrupted memory. | 681 // If these asserts fire, you probably corrupted memory. |
| 639 #if ENABLE(ASSERT) | 682 #if ENABLE(ASSERT) |
| 640 size_t slotSize = page->bucket->slotSize; | 683 size_t slotSize = page->bucket->slotSize; |
| 641 size_t rawSize = partitionPageGetRawSize(page); | 684 size_t rawSize = partitionPageGetRawSize(page); |
| 642 if (rawSize) | 685 if (rawSize) |
| 643 slotSize = rawSize; | 686 slotSize = rawSize; |
| 644 partitionCookieCheckValue(ptr); | 687 partitionCookieCheckValue(ptr); |
| 645 partitionCookieCheckValue(reinterpret_cast<char*>(ptr) + slotSize - kCookieS
ize); | 688 partitionCookieCheckValue(reinterpret_cast<char*>(ptr) + slotSize - kCookieS
ize); |
| 646 memset(ptr, kFreedByte, slotSize); | 689 memset(ptr, kFreedByte, slotSize); |
| 647 #endif | 690 #endif |
| 691 |
| 692 PartitionAllocHooks::maybeInvokeFreeHook(ptr); |
| 693 |
| 648 ASSERT(page->numAllocatedSlots); | 694 ASSERT(page->numAllocatedSlots); |
| 649 PartitionFreelistEntry* freelistHead = page->freelistHead; | 695 PartitionFreelistEntry* freelistHead = page->freelistHead; |
| 650 ASSERT(!freelistHead || partitionPointerIsValid(freelistHead)); | 696 ASSERT(!freelistHead || partitionPointerIsValid(freelistHead)); |
| 651 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ptr != freelistHead); // Catches an
immediate double free. | 697 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ptr != freelistHead); // Catches an
immediate double free. |
| 652 ASSERT_WITH_SECURITY_IMPLICATION(!freelistHead || ptr != partitionFreelistMa
sk(freelistHead->next)); // Look for double free one level deeper in debug. | 698 ASSERT_WITH_SECURITY_IMPLICATION(!freelistHead || ptr != partitionFreelistMa
sk(freelistHead->next)); // Look for double free one level deeper in debug. |
| 653 PartitionFreelistEntry* entry = static_cast<PartitionFreelistEntry*>(ptr); | 699 PartitionFreelistEntry* entry = static_cast<PartitionFreelistEntry*>(ptr); |
| 654 entry->next = partitionFreelistMask(freelistHead); | 700 entry->next = partitionFreelistMask(freelistHead); |
| 655 page->freelistHead = entry; | 701 page->freelistHead = entry; |
| 656 --page->numAllocatedSlots; | 702 --page->numAllocatedSlots; |
| 657 if (UNLIKELY(page->numAllocatedSlots <= 0)) { | 703 if (UNLIKELY(page->numAllocatedSlots <= 0)) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 using WTF::partitionAlloc; | 860 using WTF::partitionAlloc; |
| 815 using WTF::partitionFree; | 861 using WTF::partitionFree; |
| 816 using WTF::partitionAllocGeneric; | 862 using WTF::partitionAllocGeneric; |
| 817 using WTF::partitionFreeGeneric; | 863 using WTF::partitionFreeGeneric; |
| 818 using WTF::partitionReallocGeneric; | 864 using WTF::partitionReallocGeneric; |
| 819 using WTF::partitionAllocActualSize; | 865 using WTF::partitionAllocActualSize; |
| 820 using WTF::partitionAllocSupportsGetSize; | 866 using WTF::partitionAllocSupportsGetSize; |
| 821 using WTF::partitionAllocGetSize; | 867 using WTF::partitionAllocGetSize; |
| 822 | 868 |
| 823 #endif // WTF_PartitionAlloc_h | 869 #endif // WTF_PartitionAlloc_h |
| OLD | NEW |