|
62 | 62 | #include "runtime/vm_version.hpp"
|
63 | 63 | #include "services/attachListener.hpp"
|
64 | 64 | #include "services/mallocTracker.hpp"
|
| 65 | +#include "services/mallocHeader.inline.hpp" |
65 | 66 | #include "services/memTracker.hpp"
|
66 | 67 | #include "services/nmtPreInit.hpp"
|
67 | 68 | #include "services/nmtCommon.hpp"
|
@@ -714,30 +715,31 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa
|
714 | 715 | return NULL;
|
715 | 716 | }
|
716 | 717 |
|
717 |
| - const size_t old_size = MallocTracker::malloc_header(memblock)->size(); |
718 |
| - |
719 |
| - // De-account the old block from NMT *before* calling the real realloc(3) since it |
720 |
| - // may invalidate old block including its header. This will also perform integrity checks |
721 |
| - // on the old block (e.g. overwriters) and mark the old header as dead. |
722 |
| - void* const old_outer_ptr = MemTracker::record_free(memblock); |
| 718 | + // Perform integrity checks on and mark the old block as dead *before* calling the real realloc(3) since it |
| 719 | + // may invalidate the old block, including its header. |
| 720 | + MallocHeader* header = MallocTracker::malloc_header(memblock); |
| 721 | + header->assert_block_integrity(); // Assert block hasn't been tampered with. |
| 722 | + const MallocHeader::FreeInfo free_info = header->free_info(); |
| 723 | + header->mark_block_as_dead(); |
723 | 724 |
|
724 | 725 | // the real realloc
|
725 |
| - ALLOW_C_FUNCTION(::realloc, void* const new_outer_ptr = ::realloc(old_outer_ptr, new_outer_size);) |
| 726 | + ALLOW_C_FUNCTION(::realloc, void* const new_outer_ptr = ::realloc(header, new_outer_size);) |
726 | 727 |
|
727 | 728 | if (new_outer_ptr == NULL) {
|
728 |
| - // If realloc(3) failed, the old block still exists. We must re-instantiate the old |
729 |
| - // NMT header then, since we marked it dead already. Otherwise subsequent os::realloc() |
730 |
| - // or os::free() calls would trigger block integrity asserts. |
731 |
| - void* p = MemTracker::record_malloc(old_outer_ptr, old_size, memflags, stack); |
732 |
| - assert(p == memblock, "sanity"); |
733 |
| - return NULL; |
| 729 | + // realloc(3) failed and the block still exists. |
| 730 | + // We have however marked it as dead, revert this change. |
| 731 | + header->revive(); |
| 732 | + return nullptr; |
734 | 733 | }
|
| 734 | + // realloc(3) succeeded, variable header now points to invalid memory and we need to deaccount the old block. |
| 735 | + MemTracker::deaccount(free_info); |
735 | 736 |
|
736 |
| - // After a successful realloc(3), we re-account the resized block with its new size |
737 |
| - // to NMT. This re-instantiates the NMT header. |
| 737 | + // After a successful realloc(3), we account the resized block with its new size |
| 738 | + // to NMT. |
738 | 739 | void* const new_inner_ptr = MemTracker::record_malloc(new_outer_ptr, size, memflags, stack);
|
739 | 740 |
|
740 | 741 | #ifdef ASSERT
|
| 742 | + size_t old_size = free_info.size; |
741 | 743 | if (old_size < size) {
|
742 | 744 | // We also zap the newly extended region.
|
743 | 745 | ::memset((char*)new_inner_ptr + old_size, uninitBlockPad, size - old_size);
|
@@ -774,7 +776,7 @@ void os::free(void *memblock) {
|
774 | 776 |
|
775 | 777 | DEBUG_ONLY(break_if_ptr_caught(memblock);)
|
776 | 778 |
|
777 |
| - // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. |
| 779 | + // When NMT is enabled this checks for heap overwrites, then deaccounts the old block. |
778 | 780 | void* const old_outer_ptr = MemTracker::record_free(memblock);
|
779 | 781 |
|
780 | 782 | ALLOW_C_FUNCTION(::free, ::free(old_outer_ptr);)
|
|
0 commit comments