Index: lib/hwasan/hwasan.cpp =================================================================== --- lib/hwasan/hwasan.cpp +++ lib/hwasan/hwasan.cpp @@ -462,6 +462,20 @@ return AddTagToPointer(p, tag); } +void __hwasan_init_globals(uptr beg, uptr end) { + struct GlobalInfo { + uptr addr, size; + }; + CHECK((end - beg) % sizeof(GlobalInfo) == 0); + + GlobalInfo *gi = reinterpret_cast(beg); + uptr count = (end - beg) / sizeof(*gi); + + for (uptr i = 0; i < count; ++i) + TagMemoryAligned(UntagAddr(gi[i].addr), gi[i].size, + GetTagFromPointer(gi[i].addr)); +} + void __hwasan_handle_longjmp(const void *sp_dst) { uptr dst = (uptr)sp_dst; // HWASan does not support tagged SP. Index: lib/hwasan/hwasan_allocator.cpp =================================================================== --- lib/hwasan/hwasan_allocator.cpp +++ lib/hwasan/hwasan_allocator.cpp @@ -327,13 +327,13 @@ if (!ptr) return SetErrnoOnNull(HwasanAllocate(stack, size, sizeof(u64), false)); + bool PointerIsMine = allocator.PointerIsMine(UntagPtr(ptr)); #if HWASAN_WITH_INTERCEPTORS - // A tag of 0 means that this is a system allocator allocation, so we must use - // the system allocator to realloc it. - if (!flags()->disable_allocator_tagging && GetTagFromPointer((uptr)ptr) == 0) + if (GetTagFromPointer((uptr)ptr) == 0 && !PointerIsMine) return REAL(realloc)(ptr, size); #endif + CHECK(PointerIsMine); if (size == 0) { HwasanDeallocate(stack, ptr); return nullptr; @@ -396,13 +396,16 @@ } void hwasan_free(void *ptr, StackTrace *stack) { + if (!ptr) + return; + + bool PointerIsMine = allocator.PointerIsMine(UntagPtr(ptr)); #if HWASAN_WITH_INTERCEPTORS - // A tag of 0 means that this is a system allocator allocation, so we must use - // the system allocator to free it. - if (!flags()->disable_allocator_tagging && GetTagFromPointer((uptr)ptr) == 0) + if (GetTagFromPointer((uptr)ptr) == 0 && !PointerIsMine) return REAL(free)(ptr); #endif + CHECK(PointerIsMine); return HwasanDeallocate(stack, ptr); } Index: lib/hwasan/hwasan_interface_internal.h =================================================================== --- lib/hwasan/hwasan_interface_internal.h +++ lib/hwasan/hwasan_interface_internal.h @@ -206,6 +206,8 @@ void *__hwasan_memset(void *s, int c, uptr n); SANITIZER_INTERFACE_ATTRIBUTE void *__hwasan_memmove(void *dest, const void *src, uptr n); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_init_globals(uptr, uptr); } // extern "C" #endif // HWASAN_INTERFACE_INTERNAL_H Index: test/hwasan/TestCases/globals.c =================================================================== --- test/hwasan/TestCases/globals.c +++ test/hwasan/TestCases/globals.c @@ -0,0 +1,21 @@ +// RUN: %clang_hwasan %s -DCHECK_STATIC -mllvm -hwasan-instrument-globals -o %t -Wl,--no-relax && not %run %t 2>&1 | FileCheck %s +// RUN: %clang_hwasan %s -mllvm -hwasan-instrument-globals -o %t -Wl,--no-relax && not %run %t 2>&1 | FileCheck %s +// REQUIRES: stable-runtime + +#include +#ifndef CHECK_STATIC +long Q = 42; +#else +static long Q = 42; +#endif + +int main() { + long *P = &Q; + memset(P, 0, 32); + // CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address + // CHECK: WRITE of size 32 at {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem) + // CHECK: Invalid access starting at offset [16, 32) + // CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes): + // CHECK: =>{{.*}}[[PTR_TAG]]{{[[:space:]]\[}}[[MEM_TAG]] + return 0; +}