diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp --- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -204,13 +204,16 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { CHECK(tagged_ptr); HWASAN_FREE_HOOK(tagged_ptr); + void *untagged_ptr = InTaggableRegion(reinterpret_cast(tagged_ptr)) + ? UntagPtr(tagged_ptr) + : tagged_ptr; + if (!allocator.PointerIsMine(untagged_ptr)) + ReportWildFree(stack, + reinterpret_cast(untagged_ptr)); // does not return. if (!PointerAndMemoryTagsMatch(tagged_ptr)) ReportInvalidFree(stack, reinterpret_cast(tagged_ptr)); - void *untagged_ptr = InTaggableRegion(reinterpret_cast(tagged_ptr)) - ? UntagPtr(tagged_ptr) - : tagged_ptr; void *aligned_ptr = reinterpret_cast( RoundDownTo(reinterpret_cast(untagged_ptr), kShadowAlignment)); tag_t pointer_tag = GetTagFromPointer(reinterpret_cast(tagged_ptr)); diff --git a/compiler-rt/lib/hwasan/hwasan_report.h b/compiler-rt/lib/hwasan/hwasan_report.h --- a/compiler-rt/lib/hwasan/hwasan_report.h +++ b/compiler-rt/lib/hwasan/hwasan_report.h @@ -28,7 +28,7 @@ const u8 *expected); void ReportRegisters(uptr *registers_frame, uptr pc); void ReportAtExitStatistics(); - +void ReportWildFree(StackTrace *stack, uptr addr); } // namespace __hwasan diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp --- a/compiler-rt/lib/hwasan/hwasan_report.cpp +++ b/compiler-rt/lib/hwasan/hwasan_report.cpp @@ -723,6 +723,20 @@ frame[29], frame[30], reinterpret_cast(frame) + 256); } +void ReportWildFree(StackTrace *stack, uptr untagged_addr) { + ScopedReport report(/*fatal=*/true); + uptr pc = stack->size ? stack->trace[0] : 0; + const Thread *thread = GetCurrentThread(); + if (thread) { + Report("ERROR: %s: wild-free on address %p at pc %p on thread T%zd\n", + SanitizerToolName, untagged_addr, pc, thread->unique_id()); + } else { + Report("ERROR: %s: wild-free on address %p at pc %p on unknown thread\n", + SanitizerToolName, untagged_addr, pc); + } + stack->Print(); +} + } // namespace __hwasan void __hwasan_set_error_report_callback(void (*callback)(const char *)) { diff --git a/compiler-rt/test/hwasan/TestCases/wild-free.c b/compiler-rt/test/hwasan/TestCases/wild-free.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/wild-free.c @@ -0,0 +1,15 @@ +// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime + +#include + +int main() { + char *p = (char *)malloc(1); + free(p + 0x10000000000); + // CHECK: ERROR: HWAddressSanitizer: wild-free on address {{.*}} at pc {{.*}} on thread T{{[0-9]+}} + // CHECK: #1 {{.*}} in main {{.*}}wild-free.c:[[@LINE-2]] + // CHECK-NOT: Segmentation fault + // CHECK-NOT: SIGSEGV + return 0; +}