diff options
author | Andreas Kling <kling@serenityos.org> | 2021-03-09 13:27:05 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-03-09 13:29:41 +0100 |
commit | 1381720d1dfeed795a4021a261ac91bd677bfde0 (patch) | |
tree | 3a024c2c6e8be732ff2b854133bdddb99a6aae57 /Userland | |
parent | 38fc522f5d22952959b754015a1d52d6e44977f0 (diff) | |
download | serenity-1381720d1dfeed795a4021a261ac91bd677bfde0.zip |
UserspaceEmulator: Don't assume entire malloc block is chunked
Accesses in the header (or trailing padding) of a malloc block should
not be associated with any mallocation since only the chunk-sized slots
actually get returned by malloc.
Basically, allow address-to-chunk lookup to fail, and handle such
failures gracefully at call sites.
Fixes #5706.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/MallocTracer.cpp | 25 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/MallocTracer.h | 15 |
2 files changed, 27 insertions, 13 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp b/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp index 20e64449e1..c98421f6b0 100644 --- a/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp +++ b/Userland/DevTools/UserspaceEmulator/MallocTracer.cpp @@ -101,24 +101,34 @@ void MallocTracer::target_did_malloc(Badge<Emulator>, FlatPtr address, size_t si dbgln("Tracking malloc block @ {:p} with chunk_size={}, chunk_count={}", malloc_data.address, malloc_data.chunk_size, malloc_data.mallocations.size()); } - mmap_region.malloc_metadata()->mallocation_for_address(address) = { address, size, true, false, m_emulator.raw_backtrace(), Vector<FlatPtr>() }; + auto* mallocation = mmap_region.malloc_metadata()->mallocation_for_address(address); + VERIFY(mallocation); + *mallocation = { address, size, true, false, m_emulator.raw_backtrace(), Vector<FlatPtr>() }; } -ALWAYS_INLINE Mallocation& MallocRegionMetadata::mallocation_for_address(FlatPtr address) const +ALWAYS_INLINE Mallocation* MallocRegionMetadata::mallocation_for_address(FlatPtr address) const { - return const_cast<Mallocation&>(this->mallocations[chunk_index_for_address(address)]); + auto index = chunk_index_for_address(address); + if (!index.has_value()) + return nullptr; + return &const_cast<Mallocation&>(this->mallocations[index.value()]); } -ALWAYS_INLINE size_t MallocRegionMetadata::chunk_index_for_address(FlatPtr address) const +ALWAYS_INLINE Optional<size_t> MallocRegionMetadata::chunk_index_for_address(FlatPtr address) const { bool is_chunked_block = chunk_size <= size_classes[num_size_classes - 1]; if (!is_chunked_block) { // This is a BigAllocationBlock return 0; } - auto chunk_offset = address - (this->address + sizeof(ChunkedBlock)); - VERIFY(this->chunk_size); - return chunk_offset / this->chunk_size; + auto offset_into_block = address - this->address; + if (offset_into_block < sizeof(ChunkedBlock)) + return 0; + auto chunk_offset = offset_into_block - sizeof(ChunkedBlock); + auto chunk_index = chunk_offset / this->chunk_size; + if (chunk_index >= mallocations.size()) + return {}; + return chunk_index; } void MallocTracer::target_did_free(Badge<Emulator>, FlatPtr address) @@ -382,4 +392,5 @@ void MallocTracer::dump_leak_report() else reportln("\n=={}== \033[31;1m{} leak(s) found: {} byte(s) leaked\033[0m", getpid(), leaks_found, bytes_leaked); } + } diff --git a/Userland/DevTools/UserspaceEmulator/MallocTracer.h b/Userland/DevTools/UserspaceEmulator/MallocTracer.h index 6329e66da9..1d50105c54 100644 --- a/Userland/DevTools/UserspaceEmulator/MallocTracer.h +++ b/Userland/DevTools/UserspaceEmulator/MallocTracer.h @@ -60,8 +60,8 @@ public: FlatPtr address { 0 }; size_t chunk_size { 0 }; - size_t chunk_index_for_address(FlatPtr) const; - Mallocation& mallocation_for_address(FlatPtr) const; + Optional<size_t> chunk_index_for_address(FlatPtr) const; + Mallocation* mallocation_for_address(FlatPtr) const; Vector<Mallocation> mallocations; }; @@ -103,11 +103,14 @@ ALWAYS_INLINE Mallocation* MallocTracer::find_mallocation(const Region& region, auto* malloc_data = static_cast<MmapRegion&>(const_cast<Region&>(region)).malloc_metadata(); if (!malloc_data) return nullptr; - auto& mallocation = malloc_data->mallocation_for_address(address); - if (!mallocation.used) + auto* mallocation = malloc_data->mallocation_for_address(address); + if (!mallocation) return nullptr; - VERIFY(mallocation.contains(address)); - return &mallocation; + if (!mallocation->used) + return nullptr; + if (!mallocation->contains(address)) + return nullptr; + return mallocation; } } |