[ASan] Fix crash in __asan_region_is_poisoned at application memory boundaries (#180223)
`__asan_region_is_poisoned()` can crash when called on a region fully
contained in the last 8 bytes (shadow-granularity) before the end of an
ASan application memory range (kLowMemEnd / kMidMemEnd / kHighMemEnd).
The function performs a fast-path check by rounding UP the begin address
and rounding DOWN the end address of the region (aligned to
`ASAN_SHADOW_GRANULARITY`) and then scanning the corresponding shadow
range via `MemToShadow()` and `mem_is_zero()`. The implementation of
`MemToShadow()` assumes that `RoundUpTo(beg, ASAN_SHADOW_GRANULARITY)`
remains within the same application memory range. That assumption is
incorrect near upper bound of a range: for example, begin address within
the last 8 bytes of the high memory range
(`kHighMemEnd=0x0000'7fff'ffff'ffff`), which is the max user address of
VAS on x86_64, may be rounded UP so it crosses the upper bound
kHighMemEnd. In such cases MemToShadow() is invoked on an out-of-range
address and crashes.
Precisely, the following calls crash in `MemToShadow(aligned_b)` because
`aligned_b = RoundUpTo(beg, ASAN_SHADOW_GRANULARITY)` returns
`0x0000'8000'0000'0000` which is 1 byte beyond the VAS:
`__asan_region_is_poisoned((void*)0x0000'7fff'ffff'fff9, size); // 1 <=
size <= 6
__asan_region_is_poisoned((void*)0x0000'7fff'ffff'fffa, size); // 1 <=
size <= 5
__asan_region_is_poisoned((void*)0x0000'7fff'ffff'fffb, size); // 1 <=
size <= 4
__asan_region_is_poisoned((void*)0x0000'7fff'ffff'fffc, size); // 1 <=
size <= 3
__asan_region_is_poisoned((void*)0x0000'7fff'ffff'fffd, size); // 1 <=
size <= 2
__asan_region_is_poisoned((void*)0x0000'7fff'ffff'fffe, size); // size =
1`
Fix this by detecting cases earlier where the shadow range is empty
(aligned_e < aligned_b) and returning earlier without calling
MemToShadow() or mem_is_zero().
Add tests checking regions at the ends of ASan LowMem, MidMem, and
HighMem application memory ranges to ensure __asan_region_is_poisoned()
no longer crashes on these boundary cases.
GitOrigin-RevId: 35b5d13c45cd9c0d7c38120eae536f17ec9541a3
2 files changed