1353944Sdim//===-- asan_poisoning.cpp ------------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is a part of AddressSanitizer, an address sanity checker. 10353944Sdim// 11353944Sdim// Shadow memory poisoning by ASan RTL and by user application. 12353944Sdim//===----------------------------------------------------------------------===// 13353944Sdim 14353944Sdim#include "asan_poisoning.h" 15353944Sdim#include "asan_report.h" 16353944Sdim#include "asan_stack.h" 17353944Sdim#include "sanitizer_common/sanitizer_atomic.h" 18353944Sdim#include "sanitizer_common/sanitizer_libc.h" 19353944Sdim#include "sanitizer_common/sanitizer_flags.h" 20353944Sdim 21353944Sdimnamespace __asan { 22353944Sdim 23353944Sdimstatic atomic_uint8_t can_poison_memory; 24353944Sdim 25353944Sdimvoid SetCanPoisonMemory(bool value) { 26353944Sdim atomic_store(&can_poison_memory, value, memory_order_release); 27353944Sdim} 28353944Sdim 29353944Sdimbool CanPoisonMemory() { 30353944Sdim return atomic_load(&can_poison_memory, memory_order_acquire); 31353944Sdim} 32353944Sdim 33353944Sdimvoid PoisonShadow(uptr addr, uptr size, u8 value) { 34353944Sdim if (value && !CanPoisonMemory()) return; 35353944Sdim CHECK(AddrIsAlignedByGranularity(addr)); 36353944Sdim CHECK(AddrIsInMem(addr)); 37353944Sdim CHECK(AddrIsAlignedByGranularity(addr + size)); 38353944Sdim CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY)); 39353944Sdim CHECK(REAL(memset)); 40353944Sdim FastPoisonShadow(addr, size, value); 41353944Sdim} 42353944Sdim 43353944Sdimvoid PoisonShadowPartialRightRedzone(uptr addr, 44353944Sdim uptr size, 45353944Sdim uptr redzone_size, 46353944Sdim u8 value) { 47353944Sdim if (!CanPoisonMemory()) return; 48353944Sdim CHECK(AddrIsAlignedByGranularity(addr)); 49353944Sdim CHECK(AddrIsInMem(addr)); 50353944Sdim FastPoisonShadowPartialRightRedzone(addr, size, redzone_size, value); 51353944Sdim} 52353944Sdim 53353944Sdimstruct ShadowSegmentEndpoint { 54353944Sdim u8 *chunk; 55353944Sdim s8 offset; // in [0, SHADOW_GRANULARITY) 56353944Sdim s8 value; // = *chunk; 57353944Sdim 58353944Sdim explicit ShadowSegmentEndpoint(uptr address) { 59353944Sdim chunk = (u8*)MemToShadow(address); 60353944Sdim offset = address & (SHADOW_GRANULARITY - 1); 61353944Sdim value = *chunk; 62353944Sdim } 63353944Sdim}; 64353944Sdim 65353944Sdimvoid FlushUnneededASanShadowMemory(uptr p, uptr size) { 66353944Sdim // Since asan's mapping is compacting, the shadow chunk may be 67353944Sdim // not page-aligned, so we only flush the page-aligned portion. 68353944Sdim ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size)); 69353944Sdim} 70353944Sdim 71353944Sdimvoid AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) { 72353944Sdim uptr end = ptr + size; 73353944Sdim if (Verbosity()) { 74353944Sdim Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n", 75353944Sdim poison ? "" : "un", ptr, end, size); 76353944Sdim if (Verbosity() >= 2) 77353944Sdim PRINT_CURRENT_STACK(); 78353944Sdim } 79353944Sdim CHECK(size); 80353944Sdim CHECK_LE(size, 4096); 81353944Sdim CHECK(IsAligned(end, SHADOW_GRANULARITY)); 82353944Sdim if (!IsAligned(ptr, SHADOW_GRANULARITY)) { 83353944Sdim *(u8 *)MemToShadow(ptr) = 84353944Sdim poison ? static_cast<u8>(ptr % SHADOW_GRANULARITY) : 0; 85353944Sdim ptr |= SHADOW_GRANULARITY - 1; 86353944Sdim ptr++; 87353944Sdim } 88353944Sdim for (; ptr < end; ptr += SHADOW_GRANULARITY) 89353944Sdim *(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0; 90353944Sdim} 91353944Sdim 92353944Sdim} // namespace __asan 93353944Sdim 94353944Sdim// ---------------------- Interface ---------------- {{{1 95353944Sdimusing namespace __asan; 96353944Sdim 97353944Sdim// Current implementation of __asan_(un)poison_memory_region doesn't check 98353944Sdim// that user program (un)poisons the memory it owns. It poisons memory 99353944Sdim// conservatively, and unpoisons progressively to make sure asan shadow 100353944Sdim// mapping invariant is preserved (see detailed mapping description here: 101353944Sdim// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm). 102353944Sdim// 103353944Sdim// * if user asks to poison region [left, right), the program poisons 104353944Sdim// at least [left, AlignDown(right)). 105353944Sdim// * if user asks to unpoison region [left, right), the program unpoisons 106353944Sdim// at most [AlignDown(left), right). 107353944Sdimvoid __asan_poison_memory_region(void const volatile *addr, uptr size) { 108353944Sdim if (!flags()->allow_user_poisoning || size == 0) return; 109353944Sdim uptr beg_addr = (uptr)addr; 110353944Sdim uptr end_addr = beg_addr + size; 111353944Sdim VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr, 112353944Sdim (void *)end_addr); 113353944Sdim ShadowSegmentEndpoint beg(beg_addr); 114353944Sdim ShadowSegmentEndpoint end(end_addr); 115353944Sdim if (beg.chunk == end.chunk) { 116353944Sdim CHECK_LT(beg.offset, end.offset); 117353944Sdim s8 value = beg.value; 118353944Sdim CHECK_EQ(value, end.value); 119353944Sdim // We can only poison memory if the byte in end.offset is unaddressable. 120353944Sdim // No need to re-poison memory if it is poisoned already. 121353944Sdim if (value > 0 && value <= end.offset) { 122353944Sdim if (beg.offset > 0) { 123353944Sdim *beg.chunk = Min(value, beg.offset); 124353944Sdim } else { 125353944Sdim *beg.chunk = kAsanUserPoisonedMemoryMagic; 126353944Sdim } 127353944Sdim } 128353944Sdim return; 129353944Sdim } 130353944Sdim CHECK_LT(beg.chunk, end.chunk); 131353944Sdim if (beg.offset > 0) { 132353944Sdim // Mark bytes from beg.offset as unaddressable. 133353944Sdim if (beg.value == 0) { 134353944Sdim *beg.chunk = beg.offset; 135353944Sdim } else { 136353944Sdim *beg.chunk = Min(beg.value, beg.offset); 137353944Sdim } 138353944Sdim beg.chunk++; 139353944Sdim } 140353944Sdim REAL(memset)(beg.chunk, kAsanUserPoisonedMemoryMagic, end.chunk - beg.chunk); 141353944Sdim // Poison if byte in end.offset is unaddressable. 142353944Sdim if (end.value > 0 && end.value <= end.offset) { 143353944Sdim *end.chunk = kAsanUserPoisonedMemoryMagic; 144353944Sdim } 145353944Sdim} 146353944Sdim 147353944Sdimvoid __asan_unpoison_memory_region(void const volatile *addr, uptr size) { 148353944Sdim if (!flags()->allow_user_poisoning || size == 0) return; 149353944Sdim uptr beg_addr = (uptr)addr; 150353944Sdim uptr end_addr = beg_addr + size; 151353944Sdim VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr, 152353944Sdim (void *)end_addr); 153353944Sdim ShadowSegmentEndpoint beg(beg_addr); 154353944Sdim ShadowSegmentEndpoint end(end_addr); 155353944Sdim if (beg.chunk == end.chunk) { 156353944Sdim CHECK_LT(beg.offset, end.offset); 157353944Sdim s8 value = beg.value; 158353944Sdim CHECK_EQ(value, end.value); 159353944Sdim // We unpoison memory bytes up to enbytes up to end.offset if it is not 160353944Sdim // unpoisoned already. 161353944Sdim if (value != 0) { 162353944Sdim *beg.chunk = Max(value, end.offset); 163353944Sdim } 164353944Sdim return; 165353944Sdim } 166353944Sdim CHECK_LT(beg.chunk, end.chunk); 167353944Sdim if (beg.offset > 0) { 168353944Sdim *beg.chunk = 0; 169353944Sdim beg.chunk++; 170353944Sdim } 171353944Sdim REAL(memset)(beg.chunk, 0, end.chunk - beg.chunk); 172353944Sdim if (end.offset > 0 && end.value != 0) { 173353944Sdim *end.chunk = Max(end.value, end.offset); 174353944Sdim } 175353944Sdim} 176353944Sdim 177353944Sdimint __asan_address_is_poisoned(void const volatile *addr) { 178353944Sdim return __asan::AddressIsPoisoned((uptr)addr); 179353944Sdim} 180353944Sdim 181353944Sdimuptr __asan_region_is_poisoned(uptr beg, uptr size) { 182353944Sdim if (!size) return 0; 183353944Sdim uptr end = beg + size; 184353944Sdim if (SANITIZER_MYRIAD2) { 185353944Sdim // On Myriad, address not in DRAM range need to be treated as 186353944Sdim // unpoisoned. 187353944Sdim if (!AddrIsInMem(beg) && !AddrIsInShadow(beg)) return 0; 188353944Sdim if (!AddrIsInMem(end) && !AddrIsInShadow(end)) return 0; 189353944Sdim } else { 190353944Sdim if (!AddrIsInMem(beg)) return beg; 191353944Sdim if (!AddrIsInMem(end)) return end; 192353944Sdim } 193353944Sdim CHECK_LT(beg, end); 194353944Sdim uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY); 195353944Sdim uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY); 196353944Sdim uptr shadow_beg = MemToShadow(aligned_b); 197353944Sdim uptr shadow_end = MemToShadow(aligned_e); 198353944Sdim // First check the first and the last application bytes, 199353944Sdim // then check the SHADOW_GRANULARITY-aligned region by calling 200353944Sdim // mem_is_zero on the corresponding shadow. 201353944Sdim if (!__asan::AddressIsPoisoned(beg) && 202353944Sdim !__asan::AddressIsPoisoned(end - 1) && 203353944Sdim (shadow_end <= shadow_beg || 204353944Sdim __sanitizer::mem_is_zero((const char *)shadow_beg, 205353944Sdim shadow_end - shadow_beg))) 206353944Sdim return 0; 207353944Sdim // The fast check failed, so we have a poisoned byte somewhere. 208353944Sdim // Find it slowly. 209353944Sdim for (; beg < end; beg++) 210353944Sdim if (__asan::AddressIsPoisoned(beg)) 211353944Sdim return beg; 212353944Sdim UNREACHABLE("mem_is_zero returned false, but poisoned byte was not found"); 213353944Sdim return 0; 214353944Sdim} 215353944Sdim 216353944Sdim#define CHECK_SMALL_REGION(p, size, isWrite) \ 217353944Sdim do { \ 218353944Sdim uptr __p = reinterpret_cast<uptr>(p); \ 219353944Sdim uptr __size = size; \ 220353944Sdim if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \ 221353944Sdim __asan::AddressIsPoisoned(__p + __size - 1))) { \ 222353944Sdim GET_CURRENT_PC_BP_SP; \ 223353944Sdim uptr __bad = __asan_region_is_poisoned(__p, __size); \ 224353944Sdim __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\ 225353944Sdim } \ 226353944Sdim } while (false) 227353944Sdim 228353944Sdim 229353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 230353944Sdimu16 __sanitizer_unaligned_load16(const uu16 *p) { 231353944Sdim CHECK_SMALL_REGION(p, sizeof(*p), false); 232353944Sdim return *p; 233353944Sdim} 234353944Sdim 235353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 236353944Sdimu32 __sanitizer_unaligned_load32(const uu32 *p) { 237353944Sdim CHECK_SMALL_REGION(p, sizeof(*p), false); 238353944Sdim return *p; 239353944Sdim} 240353944Sdim 241353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 242353944Sdimu64 __sanitizer_unaligned_load64(const uu64 *p) { 243353944Sdim CHECK_SMALL_REGION(p, sizeof(*p), false); 244353944Sdim return *p; 245353944Sdim} 246353944Sdim 247353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 248353944Sdimvoid __sanitizer_unaligned_store16(uu16 *p, u16 x) { 249353944Sdim CHECK_SMALL_REGION(p, sizeof(*p), true); 250353944Sdim *p = x; 251353944Sdim} 252353944Sdim 253353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 254353944Sdimvoid __sanitizer_unaligned_store32(uu32 *p, u32 x) { 255353944Sdim CHECK_SMALL_REGION(p, sizeof(*p), true); 256353944Sdim *p = x; 257353944Sdim} 258353944Sdim 259353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 260353944Sdimvoid __sanitizer_unaligned_store64(uu64 *p, u64 x) { 261353944Sdim CHECK_SMALL_REGION(p, sizeof(*p), true); 262353944Sdim *p = x; 263353944Sdim} 264353944Sdim 265353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 266353944Sdimvoid __asan_poison_cxx_array_cookie(uptr p) { 267353944Sdim if (SANITIZER_WORDSIZE != 64) return; 268353944Sdim if (!flags()->poison_array_cookie) return; 269353944Sdim uptr s = MEM_TO_SHADOW(p); 270353944Sdim *reinterpret_cast<u8*>(s) = kAsanArrayCookieMagic; 271353944Sdim} 272353944Sdim 273353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 274353944Sdimuptr __asan_load_cxx_array_cookie(uptr *p) { 275353944Sdim if (SANITIZER_WORDSIZE != 64) return *p; 276353944Sdim if (!flags()->poison_array_cookie) return *p; 277353944Sdim uptr s = MEM_TO_SHADOW(reinterpret_cast<uptr>(p)); 278353944Sdim u8 sval = *reinterpret_cast<u8*>(s); 279353944Sdim if (sval == kAsanArrayCookieMagic) return *p; 280353944Sdim // If sval is not kAsanArrayCookieMagic it can only be freed memory, 281353944Sdim // which means that we are going to get double-free. So, return 0 to avoid 282353944Sdim // infinite loop of destructors. We don't want to report a double-free here 283353944Sdim // though, so print a warning just in case. 284353944Sdim // CHECK_EQ(sval, kAsanHeapFreeMagic); 285353944Sdim if (sval == kAsanHeapFreeMagic) { 286353944Sdim Report("AddressSanitizer: loaded array cookie from free-d memory; " 287353944Sdim "expect a double-free report\n"); 288353944Sdim return 0; 289353944Sdim } 290353944Sdim // The cookie may remain unpoisoned if e.g. it comes from a custom 291353944Sdim // operator new defined inside a class. 292353944Sdim return *p; 293353944Sdim} 294353944Sdim 295353944Sdim// This is a simplified version of __asan_(un)poison_memory_region, which 296353944Sdim// assumes that left border of region to be poisoned is properly aligned. 297353944Sdimstatic void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) { 298353944Sdim if (size == 0) return; 299353944Sdim uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1); 300353944Sdim PoisonShadow(addr, aligned_size, 301353944Sdim do_poison ? kAsanStackUseAfterScopeMagic : 0); 302353944Sdim if (size == aligned_size) 303353944Sdim return; 304353944Sdim s8 end_offset = (s8)(size - aligned_size); 305353944Sdim s8* shadow_end = (s8*)MemToShadow(addr + aligned_size); 306353944Sdim s8 end_value = *shadow_end; 307353944Sdim if (do_poison) { 308353944Sdim // If possible, mark all the bytes mapping to last shadow byte as 309353944Sdim // unaddressable. 310353944Sdim if (end_value > 0 && end_value <= end_offset) 311353944Sdim *shadow_end = (s8)kAsanStackUseAfterScopeMagic; 312353944Sdim } else { 313353944Sdim // If necessary, mark few first bytes mapping to last shadow byte 314353944Sdim // as addressable 315353944Sdim if (end_value != 0) 316353944Sdim *shadow_end = Max(end_value, end_offset); 317353944Sdim } 318353944Sdim} 319353944Sdim 320353944Sdimvoid __asan_set_shadow_00(uptr addr, uptr size) { 321353944Sdim REAL(memset)((void *)addr, 0, size); 322353944Sdim} 323353944Sdim 324353944Sdimvoid __asan_set_shadow_f1(uptr addr, uptr size) { 325353944Sdim REAL(memset)((void *)addr, 0xf1, size); 326353944Sdim} 327353944Sdim 328353944Sdimvoid __asan_set_shadow_f2(uptr addr, uptr size) { 329353944Sdim REAL(memset)((void *)addr, 0xf2, size); 330353944Sdim} 331353944Sdim 332353944Sdimvoid __asan_set_shadow_f3(uptr addr, uptr size) { 333353944Sdim REAL(memset)((void *)addr, 0xf3, size); 334353944Sdim} 335353944Sdim 336353944Sdimvoid __asan_set_shadow_f5(uptr addr, uptr size) { 337353944Sdim REAL(memset)((void *)addr, 0xf5, size); 338353944Sdim} 339353944Sdim 340353944Sdimvoid __asan_set_shadow_f8(uptr addr, uptr size) { 341353944Sdim REAL(memset)((void *)addr, 0xf8, size); 342353944Sdim} 343353944Sdim 344353944Sdimvoid __asan_poison_stack_memory(uptr addr, uptr size) { 345353944Sdim VReport(1, "poisoning: %p %zx\n", (void *)addr, size); 346353944Sdim PoisonAlignedStackMemory(addr, size, true); 347353944Sdim} 348353944Sdim 349353944Sdimvoid __asan_unpoison_stack_memory(uptr addr, uptr size) { 350353944Sdim VReport(1, "unpoisoning: %p %zx\n", (void *)addr, size); 351353944Sdim PoisonAlignedStackMemory(addr, size, false); 352353944Sdim} 353353944Sdim 354353944Sdimvoid __sanitizer_annotate_contiguous_container(const void *beg_p, 355353944Sdim const void *end_p, 356353944Sdim const void *old_mid_p, 357353944Sdim const void *new_mid_p) { 358353944Sdim if (!flags()->detect_container_overflow) return; 359353944Sdim VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p, 360353944Sdim new_mid_p); 361353944Sdim uptr beg = reinterpret_cast<uptr>(beg_p); 362353944Sdim uptr end = reinterpret_cast<uptr>(end_p); 363353944Sdim uptr old_mid = reinterpret_cast<uptr>(old_mid_p); 364353944Sdim uptr new_mid = reinterpret_cast<uptr>(new_mid_p); 365353944Sdim uptr granularity = SHADOW_GRANULARITY; 366353944Sdim if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end && 367353944Sdim IsAligned(beg, granularity))) { 368353944Sdim GET_STACK_TRACE_FATAL_HERE; 369353944Sdim ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid, 370353944Sdim &stack); 371353944Sdim } 372353944Sdim CHECK_LE(end - beg, 373353944Sdim FIRST_32_SECOND_64(1UL << 30, 1ULL << 34)); // Sanity check. 374353944Sdim 375353944Sdim uptr a = RoundDownTo(Min(old_mid, new_mid), granularity); 376353944Sdim uptr c = RoundUpTo(Max(old_mid, new_mid), granularity); 377353944Sdim uptr d1 = RoundDownTo(old_mid, granularity); 378353944Sdim // uptr d2 = RoundUpTo(old_mid, granularity); 379353944Sdim // Currently we should be in this state: 380353944Sdim // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good. 381353944Sdim // Make a quick sanity check that we are indeed in this state. 382353944Sdim // 383353944Sdim // FIXME: Two of these three checks are disabled until we fix 384353944Sdim // https://github.com/google/sanitizers/issues/258. 385353944Sdim // if (d1 != d2) 386353944Sdim // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1); 387353944Sdim if (a + granularity <= d1) 388353944Sdim CHECK_EQ(*(u8*)MemToShadow(a), 0); 389353944Sdim // if (d2 + granularity <= c && c <= end) 390353944Sdim // CHECK_EQ(*(u8 *)MemToShadow(c - granularity), 391353944Sdim // kAsanContiguousContainerOOBMagic); 392353944Sdim 393353944Sdim uptr b1 = RoundDownTo(new_mid, granularity); 394353944Sdim uptr b2 = RoundUpTo(new_mid, granularity); 395353944Sdim // New state: 396353944Sdim // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good. 397353944Sdim PoisonShadow(a, b1 - a, 0); 398353944Sdim PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic); 399353944Sdim if (b1 != b2) { 400353944Sdim CHECK_EQ(b2 - b1, granularity); 401353944Sdim *(u8*)MemToShadow(b1) = static_cast<u8>(new_mid - b1); 402353944Sdim } 403353944Sdim} 404353944Sdim 405353944Sdimconst void *__sanitizer_contiguous_container_find_bad_address( 406353944Sdim const void *beg_p, const void *mid_p, const void *end_p) { 407353944Sdim if (!flags()->detect_container_overflow) 408353944Sdim return nullptr; 409353944Sdim uptr beg = reinterpret_cast<uptr>(beg_p); 410353944Sdim uptr end = reinterpret_cast<uptr>(end_p); 411353944Sdim uptr mid = reinterpret_cast<uptr>(mid_p); 412353944Sdim CHECK_LE(beg, mid); 413353944Sdim CHECK_LE(mid, end); 414353944Sdim // Check some bytes starting from beg, some bytes around mid, and some bytes 415353944Sdim // ending with end. 416353944Sdim uptr kMaxRangeToCheck = 32; 417353944Sdim uptr r1_beg = beg; 418353944Sdim uptr r1_end = Min(beg + kMaxRangeToCheck, mid); 419353944Sdim uptr r2_beg = Max(beg, mid - kMaxRangeToCheck); 420353944Sdim uptr r2_end = Min(end, mid + kMaxRangeToCheck); 421353944Sdim uptr r3_beg = Max(end - kMaxRangeToCheck, mid); 422353944Sdim uptr r3_end = end; 423353944Sdim for (uptr i = r1_beg; i < r1_end; i++) 424353944Sdim if (AddressIsPoisoned(i)) 425353944Sdim return reinterpret_cast<const void *>(i); 426353944Sdim for (uptr i = r2_beg; i < mid; i++) 427353944Sdim if (AddressIsPoisoned(i)) 428353944Sdim return reinterpret_cast<const void *>(i); 429353944Sdim for (uptr i = mid; i < r2_end; i++) 430353944Sdim if (!AddressIsPoisoned(i)) 431353944Sdim return reinterpret_cast<const void *>(i); 432353944Sdim for (uptr i = r3_beg; i < r3_end; i++) 433353944Sdim if (!AddressIsPoisoned(i)) 434353944Sdim return reinterpret_cast<const void *>(i); 435353944Sdim return nullptr; 436353944Sdim} 437353944Sdim 438353944Sdimint __sanitizer_verify_contiguous_container(const void *beg_p, 439353944Sdim const void *mid_p, 440353944Sdim const void *end_p) { 441353944Sdim return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, 442353944Sdim end_p) == nullptr; 443353944Sdim} 444353944Sdim 445353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 446353944Sdimvoid __asan_poison_intra_object_redzone(uptr ptr, uptr size) { 447353944Sdim AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true); 448353944Sdim} 449353944Sdim 450353944Sdimextern "C" SANITIZER_INTERFACE_ATTRIBUTE 451353944Sdimvoid __asan_unpoison_intra_object_redzone(uptr ptr, uptr size) { 452353944Sdim AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, false); 453353944Sdim} 454353944Sdim 455353944Sdim// --- Implementation of LSan-specific functions --- {{{1 456353944Sdimnamespace __lsan { 457353944Sdimbool WordIsPoisoned(uptr addr) { 458353944Sdim return (__asan_region_is_poisoned(addr, sizeof(uptr)) != 0); 459353944Sdim} 460353944Sdim} 461