1 1.1 mrg //===-- asan_poisoning.cpp ------------------------------------------------===// 2 1.1 mrg // 3 1.1 mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 mrg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 mrg // 7 1.1 mrg //===----------------------------------------------------------------------===// 8 1.1 mrg // 9 1.1 mrg // This file is a part of AddressSanitizer, an address sanity checker. 10 1.1 mrg // 11 1.1 mrg // Shadow memory poisoning by ASan RTL and by user application. 12 1.1 mrg //===----------------------------------------------------------------------===// 13 1.1 mrg 14 1.1 mrg #include "asan_poisoning.h" 15 1.1 mrg #include "asan_report.h" 16 1.1 mrg #include "asan_stack.h" 17 1.1 mrg #include "sanitizer_common/sanitizer_atomic.h" 18 1.1 mrg #include "sanitizer_common/sanitizer_libc.h" 19 1.1 mrg #include "sanitizer_common/sanitizer_flags.h" 20 1.1 mrg 21 1.1 mrg namespace __asan { 22 1.1 mrg 23 1.1 mrg static atomic_uint8_t can_poison_memory; 24 1.1 mrg 25 1.1 mrg void SetCanPoisonMemory(bool value) { 26 1.1 mrg atomic_store(&can_poison_memory, value, memory_order_release); 27 1.1 mrg } 28 1.1 mrg 29 1.1 mrg bool CanPoisonMemory() { 30 1.1 mrg return atomic_load(&can_poison_memory, memory_order_acquire); 31 1.1 mrg } 32 1.1 mrg 33 1.1 mrg void PoisonShadow(uptr addr, uptr size, u8 value) { 34 1.1 mrg if (value && !CanPoisonMemory()) return; 35 1.1 mrg CHECK(AddrIsAlignedByGranularity(addr)); 36 1.1 mrg CHECK(AddrIsInMem(addr)); 37 1.1 mrg CHECK(AddrIsAlignedByGranularity(addr + size)); 38 1.1 mrg CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY)); 39 1.1 mrg CHECK(REAL(memset)); 40 1.1 mrg FastPoisonShadow(addr, size, value); 41 1.1 mrg } 42 1.1 mrg 43 1.1 mrg void PoisonShadowPartialRightRedzone(uptr addr, 44 1.1 mrg uptr size, 45 1.1 mrg uptr redzone_size, 46 1.1 mrg u8 value) { 47 1.1 mrg if (!CanPoisonMemory()) return; 48 1.1 mrg CHECK(AddrIsAlignedByGranularity(addr)); 49 1.1 mrg CHECK(AddrIsInMem(addr)); 50 1.1 mrg FastPoisonShadowPartialRightRedzone(addr, size, redzone_size, value); 51 1.1 mrg } 52 1.1 mrg 53 1.1 mrg struct ShadowSegmentEndpoint { 54 1.1 mrg u8 *chunk; 55 1.1 mrg s8 offset; // in [0, SHADOW_GRANULARITY) 56 1.1 mrg s8 value; // = *chunk; 57 1.1 mrg 58 1.1 mrg explicit ShadowSegmentEndpoint(uptr address) { 59 1.1 mrg chunk = (u8*)MemToShadow(address); 60 1.1 mrg offset = address & (SHADOW_GRANULARITY - 1); 61 1.1 mrg value = *chunk; 62 1.1 mrg } 63 1.1 mrg }; 64 1.1 mrg 65 1.1 mrg void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) { 66 1.1 mrg uptr end = ptr + size; 67 1.1 mrg if (Verbosity()) { 68 1.1 mrg Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n", 69 1.1 mrg poison ? "" : "un", (void *)ptr, (void *)end, size); 70 1.1 mrg if (Verbosity() >= 2) 71 1.1 mrg PRINT_CURRENT_STACK(); 72 1.1 mrg } 73 1.1 mrg CHECK(size); 74 1.1 mrg CHECK_LE(size, 4096); 75 1.1 mrg CHECK(IsAligned(end, SHADOW_GRANULARITY)); 76 1.1 mrg if (!IsAligned(ptr, SHADOW_GRANULARITY)) { 77 1.1 mrg *(u8 *)MemToShadow(ptr) = 78 1.1 mrg poison ? static_cast<u8>(ptr % SHADOW_GRANULARITY) : 0; 79 1.1 mrg ptr |= SHADOW_GRANULARITY - 1; 80 1.1 mrg ptr++; 81 1.1 mrg } 82 1.1 mrg for (; ptr < end; ptr += SHADOW_GRANULARITY) 83 1.1 mrg *(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0; 84 1.1 mrg } 85 1.1 mrg 86 1.1 mrg } // namespace __asan 87 1.1 mrg 88 1.1 mrg // ---------------------- Interface ---------------- {{{1 89 1.1 mrg using namespace __asan; 90 1.1 mrg 91 1.1 mrg // Current implementation of __asan_(un)poison_memory_region doesn't check 92 1.1 mrg // that user program (un)poisons the memory it owns. It poisons memory 93 1.1 mrg // conservatively, and unpoisons progressively to make sure asan shadow 94 1.1 mrg // mapping invariant is preserved (see detailed mapping description here: 95 1.1 mrg // https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm). 96 1.1 mrg // 97 1.1 mrg // * if user asks to poison region [left, right), the program poisons 98 1.1 mrg // at least [left, AlignDown(right)). 99 1.1 mrg // * if user asks to unpoison region [left, right), the program unpoisons 100 1.1 mrg // at most [AlignDown(left), right). 101 1.1 mrg void __asan_poison_memory_region(void const volatile *addr, uptr size) { 102 1.1 mrg if (!flags()->allow_user_poisoning || size == 0) return; 103 1.1 mrg uptr beg_addr = (uptr)addr; 104 1.1 mrg uptr end_addr = beg_addr + size; 105 1.1 mrg VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr, 106 1.1 mrg (void *)end_addr); 107 1.1 mrg ShadowSegmentEndpoint beg(beg_addr); 108 1.1 mrg ShadowSegmentEndpoint end(end_addr); 109 1.1 mrg if (beg.chunk == end.chunk) { 110 1.1 mrg CHECK_LT(beg.offset, end.offset); 111 1.1 mrg s8 value = beg.value; 112 1.1 mrg CHECK_EQ(value, end.value); 113 1.1 mrg // We can only poison memory if the byte in end.offset is unaddressable. 114 1.1 mrg // No need to re-poison memory if it is poisoned already. 115 1.1 mrg if (value > 0 && value <= end.offset) { 116 1.1 mrg if (beg.offset > 0) { 117 1.1 mrg *beg.chunk = Min(value, beg.offset); 118 1.1 mrg } else { 119 1.1 mrg *beg.chunk = kAsanUserPoisonedMemoryMagic; 120 1.1 mrg } 121 1.1 mrg } 122 1.1 mrg return; 123 1.1 mrg } 124 1.1 mrg CHECK_LT(beg.chunk, end.chunk); 125 1.1 mrg if (beg.offset > 0) { 126 1.1 mrg // Mark bytes from beg.offset as unaddressable. 127 1.1 mrg if (beg.value == 0) { 128 1.1 mrg *beg.chunk = beg.offset; 129 1.1 mrg } else { 130 1.1 mrg *beg.chunk = Min(beg.value, beg.offset); 131 1.1 mrg } 132 1.1 mrg beg.chunk++; 133 1.1 mrg } 134 1.1 mrg REAL(memset)(beg.chunk, kAsanUserPoisonedMemoryMagic, end.chunk - beg.chunk); 135 1.1 mrg // Poison if byte in end.offset is unaddressable. 136 1.1 mrg if (end.value > 0 && end.value <= end.offset) { 137 1.1 mrg *end.chunk = kAsanUserPoisonedMemoryMagic; 138 1.1 mrg } 139 1.1 mrg } 140 1.1 mrg 141 1.1 mrg void __asan_unpoison_memory_region(void const volatile *addr, uptr size) { 142 1.1 mrg if (!flags()->allow_user_poisoning || size == 0) return; 143 1.1 mrg uptr beg_addr = (uptr)addr; 144 1.1 mrg uptr end_addr = beg_addr + size; 145 1.1 mrg VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr, 146 1.1 mrg (void *)end_addr); 147 1.1 mrg ShadowSegmentEndpoint beg(beg_addr); 148 1.1 mrg ShadowSegmentEndpoint end(end_addr); 149 1.1 mrg if (beg.chunk == end.chunk) { 150 1.1 mrg CHECK_LT(beg.offset, end.offset); 151 1.1 mrg s8 value = beg.value; 152 1.1 mrg CHECK_EQ(value, end.value); 153 1.1 mrg // We unpoison memory bytes up to enbytes up to end.offset if it is not 154 1.1 mrg // unpoisoned already. 155 1.1 mrg if (value != 0) { 156 1.1 mrg *beg.chunk = Max(value, end.offset); 157 1.1 mrg } 158 1.1 mrg return; 159 1.1 mrg } 160 1.1 mrg CHECK_LT(beg.chunk, end.chunk); 161 1.1 mrg if (beg.offset > 0) { 162 1.1 mrg *beg.chunk = 0; 163 1.1 mrg beg.chunk++; 164 1.1 mrg } 165 1.1 mrg REAL(memset)(beg.chunk, 0, end.chunk - beg.chunk); 166 1.1 mrg if (end.offset > 0 && end.value != 0) { 167 1.1 mrg *end.chunk = Max(end.value, end.offset); 168 1.1 mrg } 169 1.1 mrg } 170 1.1 mrg 171 1.1 mrg int __asan_address_is_poisoned(void const volatile *addr) { 172 1.1 mrg return __asan::AddressIsPoisoned((uptr)addr); 173 1.1 mrg } 174 1.1 mrg 175 1.1 mrg uptr __asan_region_is_poisoned(uptr beg, uptr size) { 176 1.1 mrg if (!size) 177 1.1 mrg return 0; 178 1.1 mrg uptr end = beg + size; 179 1.1 mrg if (!AddrIsInMem(beg)) 180 1.1 mrg return beg; 181 1.1 mrg if (!AddrIsInMem(end)) 182 1.1 mrg return end; 183 1.1 mrg CHECK_LT(beg, end); 184 1.1 mrg uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY); 185 1.1 mrg uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY); 186 1.1 mrg uptr shadow_beg = MemToShadow(aligned_b); 187 1.1 mrg uptr shadow_end = MemToShadow(aligned_e); 188 1.1 mrg // First check the first and the last application bytes, 189 1.1 mrg // then check the SHADOW_GRANULARITY-aligned region by calling 190 1.1 mrg // mem_is_zero on the corresponding shadow. 191 1.1 mrg if (!__asan::AddressIsPoisoned(beg) && !__asan::AddressIsPoisoned(end - 1) && 192 1.1 mrg (shadow_end <= shadow_beg || 193 1.1 mrg __sanitizer::mem_is_zero((const char *)shadow_beg, 194 1.1 mrg shadow_end - shadow_beg))) 195 1.1 mrg return 0; 196 1.1 mrg // The fast check failed, so we have a poisoned byte somewhere. 197 1.1 mrg // Find it slowly. 198 1.1 mrg for (; beg < end; beg++) 199 1.1 mrg if (__asan::AddressIsPoisoned(beg)) 200 1.1 mrg return beg; 201 1.1 mrg UNREACHABLE("mem_is_zero returned false, but poisoned byte was not found"); 202 1.1 mrg return 0; 203 1.1 mrg } 204 1.1 mrg 205 1.1 mrg #define CHECK_SMALL_REGION(p, size, isWrite) \ 206 1.1 mrg do { \ 207 1.1 mrg uptr __p = reinterpret_cast<uptr>(p); \ 208 1.1 mrg uptr __size = size; \ 209 1.1 mrg if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \ 210 1.1 mrg __asan::AddressIsPoisoned(__p + __size - 1))) { \ 211 1.1 mrg GET_CURRENT_PC_BP_SP; \ 212 1.1 mrg uptr __bad = __asan_region_is_poisoned(__p, __size); \ 213 1.1 mrg __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\ 214 1.1 mrg } \ 215 1.1 mrg } while (false) 216 1.1 mrg 217 1.1 mrg 218 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 219 1.1 mrg u16 __sanitizer_unaligned_load16(const uu16 *p) { 220 1.1 mrg CHECK_SMALL_REGION(p, sizeof(*p), false); 221 1.1 mrg return *p; 222 1.1 mrg } 223 1.1 mrg 224 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 225 1.1 mrg u32 __sanitizer_unaligned_load32(const uu32 *p) { 226 1.1 mrg CHECK_SMALL_REGION(p, sizeof(*p), false); 227 1.1 mrg return *p; 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 231 1.1 mrg u64 __sanitizer_unaligned_load64(const uu64 *p) { 232 1.1 mrg CHECK_SMALL_REGION(p, sizeof(*p), false); 233 1.1 mrg return *p; 234 1.1 mrg } 235 1.1 mrg 236 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 237 1.1 mrg void __sanitizer_unaligned_store16(uu16 *p, u16 x) { 238 1.1 mrg CHECK_SMALL_REGION(p, sizeof(*p), true); 239 1.1 mrg *p = x; 240 1.1 mrg } 241 1.1 mrg 242 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 243 1.1 mrg void __sanitizer_unaligned_store32(uu32 *p, u32 x) { 244 1.1 mrg CHECK_SMALL_REGION(p, sizeof(*p), true); 245 1.1 mrg *p = x; 246 1.1 mrg } 247 1.1 mrg 248 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 249 1.1 mrg void __sanitizer_unaligned_store64(uu64 *p, u64 x) { 250 1.1 mrg CHECK_SMALL_REGION(p, sizeof(*p), true); 251 1.1 mrg *p = x; 252 1.1 mrg } 253 1.1 mrg 254 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 255 1.1 mrg void __asan_poison_cxx_array_cookie(uptr p) { 256 1.1 mrg if (SANITIZER_WORDSIZE != 64) return; 257 1.1 mrg if (!flags()->poison_array_cookie) return; 258 1.1 mrg uptr s = MEM_TO_SHADOW(p); 259 1.1 mrg *reinterpret_cast<u8*>(s) = kAsanArrayCookieMagic; 260 1.1 mrg } 261 1.1 mrg 262 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 263 1.1 mrg uptr __asan_load_cxx_array_cookie(uptr *p) { 264 1.1 mrg if (SANITIZER_WORDSIZE != 64) return *p; 265 1.1 mrg if (!flags()->poison_array_cookie) return *p; 266 1.1 mrg uptr s = MEM_TO_SHADOW(reinterpret_cast<uptr>(p)); 267 1.1 mrg u8 sval = *reinterpret_cast<u8*>(s); 268 1.1 mrg if (sval == kAsanArrayCookieMagic) return *p; 269 1.1 mrg // If sval is not kAsanArrayCookieMagic it can only be freed memory, 270 1.1 mrg // which means that we are going to get double-free. So, return 0 to avoid 271 1.1 mrg // infinite loop of destructors. We don't want to report a double-free here 272 1.1 mrg // though, so print a warning just in case. 273 1.1 mrg // CHECK_EQ(sval, kAsanHeapFreeMagic); 274 1.1 mrg if (sval == kAsanHeapFreeMagic) { 275 1.1 mrg Report("AddressSanitizer: loaded array cookie from free-d memory; " 276 1.1 mrg "expect a double-free report\n"); 277 1.1 mrg return 0; 278 1.1 mrg } 279 1.1 mrg // The cookie may remain unpoisoned if e.g. it comes from a custom 280 1.1 mrg // operator new defined inside a class. 281 1.1 mrg return *p; 282 1.1 mrg } 283 1.1 mrg 284 1.1 mrg // This is a simplified version of __asan_(un)poison_memory_region, which 285 1.1 mrg // assumes that left border of region to be poisoned is properly aligned. 286 1.1 mrg static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) { 287 1.1 mrg if (size == 0) return; 288 1.1 mrg uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1); 289 1.1 mrg PoisonShadow(addr, aligned_size, 290 1.1 mrg do_poison ? kAsanStackUseAfterScopeMagic : 0); 291 1.1 mrg if (size == aligned_size) 292 1.1 mrg return; 293 1.1 mrg s8 end_offset = (s8)(size - aligned_size); 294 1.1 mrg s8* shadow_end = (s8*)MemToShadow(addr + aligned_size); 295 1.1 mrg s8 end_value = *shadow_end; 296 1.1 mrg if (do_poison) { 297 1.1 mrg // If possible, mark all the bytes mapping to last shadow byte as 298 1.1 mrg // unaddressable. 299 1.1 mrg if (end_value > 0 && end_value <= end_offset) 300 1.1 mrg *shadow_end = (s8)kAsanStackUseAfterScopeMagic; 301 1.1 mrg } else { 302 1.1 mrg // If necessary, mark few first bytes mapping to last shadow byte 303 1.1 mrg // as addressable 304 1.1 mrg if (end_value != 0) 305 1.1 mrg *shadow_end = Max(end_value, end_offset); 306 1.1 mrg } 307 1.1 mrg } 308 1.1 mrg 309 1.1 mrg void __asan_set_shadow_00(uptr addr, uptr size) { 310 1.1 mrg REAL(memset)((void *)addr, 0, size); 311 1.1 mrg } 312 1.1 mrg 313 1.1 mrg void __asan_set_shadow_f1(uptr addr, uptr size) { 314 1.1 mrg REAL(memset)((void *)addr, 0xf1, size); 315 1.1 mrg } 316 1.1 mrg 317 1.1 mrg void __asan_set_shadow_f2(uptr addr, uptr size) { 318 1.1 mrg REAL(memset)((void *)addr, 0xf2, size); 319 1.1 mrg } 320 1.1 mrg 321 1.1 mrg void __asan_set_shadow_f3(uptr addr, uptr size) { 322 1.1 mrg REAL(memset)((void *)addr, 0xf3, size); 323 1.1 mrg } 324 1.1 mrg 325 1.1 mrg void __asan_set_shadow_f5(uptr addr, uptr size) { 326 1.1 mrg REAL(memset)((void *)addr, 0xf5, size); 327 1.1 mrg } 328 1.1 mrg 329 1.1 mrg void __asan_set_shadow_f8(uptr addr, uptr size) { 330 1.1 mrg REAL(memset)((void *)addr, 0xf8, size); 331 1.1 mrg } 332 1.1 mrg 333 1.1 mrg void __asan_poison_stack_memory(uptr addr, uptr size) { 334 1.1 mrg VReport(1, "poisoning: %p %zx\n", (void *)addr, size); 335 1.1 mrg PoisonAlignedStackMemory(addr, size, true); 336 1.1 mrg } 337 1.1 mrg 338 1.1 mrg void __asan_unpoison_stack_memory(uptr addr, uptr size) { 339 1.1 mrg VReport(1, "unpoisoning: %p %zx\n", (void *)addr, size); 340 1.1 mrg PoisonAlignedStackMemory(addr, size, false); 341 1.1 mrg } 342 1.1 mrg 343 1.1 mrg void __sanitizer_annotate_contiguous_container(const void *beg_p, 344 1.1 mrg const void *end_p, 345 1.1 mrg const void *old_mid_p, 346 1.1 mrg const void *new_mid_p) { 347 1.1 mrg if (!flags()->detect_container_overflow) return; 348 1.1 mrg VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p, 349 1.1 mrg new_mid_p); 350 1.1 mrg uptr beg = reinterpret_cast<uptr>(beg_p); 351 1.1 mrg uptr end = reinterpret_cast<uptr>(end_p); 352 1.1 mrg uptr old_mid = reinterpret_cast<uptr>(old_mid_p); 353 1.1 mrg uptr new_mid = reinterpret_cast<uptr>(new_mid_p); 354 1.1 mrg uptr granularity = SHADOW_GRANULARITY; 355 1.1 mrg if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end && 356 1.1 mrg IsAligned(beg, granularity))) { 357 1.1 mrg GET_STACK_TRACE_FATAL_HERE; 358 1.1 mrg ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid, 359 1.1 mrg &stack); 360 1.1 mrg } 361 1.1 mrg CHECK_LE(end - beg, 362 1.1 mrg FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check. 363 1.1 mrg 364 1.1 mrg uptr a = RoundDownTo(Min(old_mid, new_mid), granularity); 365 1.1 mrg uptr c = RoundUpTo(Max(old_mid, new_mid), granularity); 366 1.1 mrg uptr d1 = RoundDownTo(old_mid, granularity); 367 1.1 mrg // uptr d2 = RoundUpTo(old_mid, granularity); 368 1.1 mrg // Currently we should be in this state: 369 1.1 mrg // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good. 370 1.1 mrg // Make a quick sanity check that we are indeed in this state. 371 1.1 mrg // 372 1.1 mrg // FIXME: Two of these three checks are disabled until we fix 373 1.1 mrg // https://github.com/google/sanitizers/issues/258. 374 1.1 mrg // if (d1 != d2) 375 1.1 mrg // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1); 376 1.1 mrg if (a + granularity <= d1) 377 1.1 mrg CHECK_EQ(*(u8*)MemToShadow(a), 0); 378 1.1 mrg // if (d2 + granularity <= c && c <= end) 379 1.1 mrg // CHECK_EQ(*(u8 *)MemToShadow(c - granularity), 380 1.1 mrg // kAsanContiguousContainerOOBMagic); 381 1.1 mrg 382 1.1 mrg uptr b1 = RoundDownTo(new_mid, granularity); 383 1.1 mrg uptr b2 = RoundUpTo(new_mid, granularity); 384 1.1 mrg // New state: 385 1.1 mrg // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good. 386 1.1 mrg PoisonShadow(a, b1 - a, 0); 387 1.1 mrg PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic); 388 1.1 mrg if (b1 != b2) { 389 1.1 mrg CHECK_EQ(b2 - b1, granularity); 390 1.1 mrg *(u8*)MemToShadow(b1) = static_cast<u8>(new_mid - b1); 391 1.1 mrg } 392 1.1 mrg } 393 1.1 mrg 394 1.1 mrg const void *__sanitizer_contiguous_container_find_bad_address( 395 1.1 mrg const void *beg_p, const void *mid_p, const void *end_p) { 396 1.1 mrg if (!flags()->detect_container_overflow) 397 1.1 mrg return nullptr; 398 1.1 mrg uptr beg = reinterpret_cast<uptr>(beg_p); 399 1.1 mrg uptr end = reinterpret_cast<uptr>(end_p); 400 1.1 mrg uptr mid = reinterpret_cast<uptr>(mid_p); 401 1.1 mrg CHECK_LE(beg, mid); 402 1.1 mrg CHECK_LE(mid, end); 403 1.1 mrg // Check some bytes starting from beg, some bytes around mid, and some bytes 404 1.1 mrg // ending with end. 405 1.1 mrg uptr kMaxRangeToCheck = 32; 406 1.1 mrg uptr r1_beg = beg; 407 1.1 mrg uptr r1_end = Min(beg + kMaxRangeToCheck, mid); 408 1.1 mrg uptr r2_beg = Max(beg, mid - kMaxRangeToCheck); 409 1.1 mrg uptr r2_end = Min(end, mid + kMaxRangeToCheck); 410 1.1 mrg uptr r3_beg = Max(end - kMaxRangeToCheck, mid); 411 1.1 mrg uptr r3_end = end; 412 1.1 mrg for (uptr i = r1_beg; i < r1_end; i++) 413 1.1 mrg if (AddressIsPoisoned(i)) 414 1.1 mrg return reinterpret_cast<const void *>(i); 415 1.1 mrg for (uptr i = r2_beg; i < mid; i++) 416 1.1 mrg if (AddressIsPoisoned(i)) 417 1.1 mrg return reinterpret_cast<const void *>(i); 418 1.1 mrg for (uptr i = mid; i < r2_end; i++) 419 1.1 mrg if (!AddressIsPoisoned(i)) 420 1.1 mrg return reinterpret_cast<const void *>(i); 421 1.1 mrg for (uptr i = r3_beg; i < r3_end; i++) 422 1.1 mrg if (!AddressIsPoisoned(i)) 423 1.1 mrg return reinterpret_cast<const void *>(i); 424 1.1 mrg return nullptr; 425 1.1 mrg } 426 1.1 mrg 427 1.1 mrg int __sanitizer_verify_contiguous_container(const void *beg_p, 428 1.1 mrg const void *mid_p, 429 1.1 mrg const void *end_p) { 430 1.1 mrg return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, 431 1.1 mrg end_p) == nullptr; 432 1.1 mrg } 433 1.1 mrg 434 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 435 1.1 mrg void __asan_poison_intra_object_redzone(uptr ptr, uptr size) { 436 1.1 mrg AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true); 437 1.1 mrg } 438 1.1 mrg 439 1.1 mrg extern "C" SANITIZER_INTERFACE_ATTRIBUTE 440 1.1 mrg void __asan_unpoison_intra_object_redzone(uptr ptr, uptr size) { 441 1.1 mrg AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, false); 442 1.1 mrg } 443 1.1 mrg 444 1.1 mrg // --- Implementation of LSan-specific functions --- {{{1 445 1.1 mrg namespace __lsan { 446 1.1 mrg bool WordIsPoisoned(uptr addr) { 447 1.1 mrg return (__asan_region_is_poisoned(addr, sizeof(uptr)) != 0); 448 1.1 mrg } 449 1.1 mrg } 450