From 7850df3de01fd3933148b04b5818ff780bb776e1 Mon Sep 17 00:00:00 2001 From: Mariusz Borsa Date: Tue, 20 Sep 2022 15:23:58 -0700 Subject: [PATCH] [Sanitizers][Darwin] Fix invalid gap found by FindAvailableMemoryRange An application running with ASAN can fail during shadow memory allocation, with an error indicating a failure to map shadow memory region due to negative size parameter passed to mmap. It turns out that the mach_vm_region_recurse() call can return an address of a module which is beyond the range of the VM address space available to the iOS process, i.e. greater than the value returned by GetMaxVirtualAddress(). It leads the FindAvailableMemoryRange function to the an incorrect conclusion that it has found a suitable gap where the shadow memory can fit in, while the shadow memory cannot be really allocated in this case. The fix just takes the maximum VM address into account, causing the function to return 0, meaning that the VM gap to fit the requested size could not be found. rdar://66530705 Differential Revision: https://reviews.llvm.org/D134836 --- compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp index 1ae69e1..23c4c66 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -1251,6 +1251,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, mach_vm_address_t start_address = (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000; + const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1; mach_vm_address_t address = start_address; mach_vm_address_t free_begin = start_address; kern_return_t kr = KERN_SUCCESS; @@ -1265,7 +1266,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, (vm_region_info_t)&vminfo, &count); if (kr == KERN_INVALID_ADDRESS) { // No more regions beyond "address", consider the gap at the end of VM. - address = GetMaxVirtualAddress() + 1; + address = max_vm_address; vmsize = 0; } else { if (max_occupied_addr) *max_occupied_addr = address + vmsize; @@ -1273,7 +1274,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, if (free_begin != address) { // We found a free region [free_begin..address-1]. uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment); - uptr gap_end = RoundDownTo((uptr)address, alignment); + uptr gap_end = RoundDownTo((uptr)Min(address, max_vm_address), alignment); uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0; if (size < gap_size) { return gap_start; -- 2.7.4