[compiler-rt] [sanitizer] Support "alloc_dealloc_mismatch" suppressions (PR #124197)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 27 08:03:35 PST 2025


https://github.com/andrewjcg updated https://github.com/llvm/llvm-project/pull/124197

>From 0f29a8fcc331d70cb1578c863ad0e4a3e5fb5a61 Mon Sep 17 00:00:00 2001
From: Andrew Gallagher <agallagher at fb.com>
Date: Thu, 23 Jan 2025 12:38:00 -0800
Subject: [PATCH] [sanitizer] Support "alloc_dealloc_mismatch" suppressions

This adds a stack-based suppressions for alloc-dealloc-mismatch
violations, using the function name to match.
---
 compiler-rt/lib/asan/asan_allocator.cpp       |  4 +-
 compiler-rt/lib/asan/asan_suppressions.cpp    | 51 ++++++++++++++-----
 compiler-rt/lib/asan/asan_suppressions.h      |  1 +
 .../suppressions-alloc-dealloc-mismatch.cpp   | 26 ++++++++++
 4 files changed, 67 insertions(+), 15 deletions(-)
 create mode 100644 compiler-rt/test/asan/TestCases/suppressions-alloc-dealloc-mismatch.cpp

diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 9e66f77217ec6b..3a55c2af65653d 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -21,6 +21,7 @@
 #include "asan_poisoning.h"
 #include "asan_report.h"
 #include "asan_stack.h"
+#include "asan_suppressions.h"
 #include "asan_thread.h"
 #include "lsan/lsan_common.h"
 #include "sanitizer_common/sanitizer_allocator_checks.h"
@@ -732,7 +733,8 @@ struct Allocator {
     if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return;
 
     if (m->alloc_type != alloc_type) {
-      if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
+      if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire) &&
+          !IsAllocDeallocMismatchSuppressed(stack)) {
         ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
                                 (AllocType)alloc_type);
       }
diff --git a/compiler-rt/lib/asan/asan_suppressions.cpp b/compiler-rt/lib/asan/asan_suppressions.cpp
index 94289d14d7e780..0eea8414ffef5b 100644
--- a/compiler-rt/lib/asan/asan_suppressions.cpp
+++ b/compiler-rt/lib/asan/asan_suppressions.cpp
@@ -26,9 +26,10 @@ static const char kInterceptorName[] = "interceptor_name";
 static const char kInterceptorViaFunction[] = "interceptor_via_fun";
 static const char kInterceptorViaLibrary[] = "interceptor_via_lib";
 static const char kODRViolation[] = "odr_violation";
+static const char kAllocDeallocMismatch[] = "alloc_dealloc_mismatch";
 static const char *kSuppressionTypes[] = {
     kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary,
-    kODRViolation};
+    kODRViolation, kAllocDeallocMismatch};
 
 SANITIZER_INTERFACE_WEAK_DEF(const char *, __asan_default_suppressions, void) {
   return "";
@@ -62,6 +63,38 @@ bool IsODRViolationSuppressed(const char *global_var_name) {
   return suppression_ctx->Match(global_var_name, kODRViolation, &s);
 }
 
+bool IsStackTraceSuppressedByFunction(const char *suppression,
+                                      const StackTrace *stack) {
+  CHECK(suppression_ctx);
+  CHECK(suppression_ctx->HasSuppressionType(suppression));
+  Symbolizer *symbolizer = Symbolizer::GetOrInit();
+  for (uptr i = 0; i < stack->size && stack->trace[i]; i++) {
+    SymbolizedStackHolder symbolized_stack(
+        symbolizer->SymbolizePC(stack->trace[i]));
+    const SymbolizedStack *frames = symbolized_stack.get();
+    CHECK(frames);
+    for (const SymbolizedStack *cur = frames; cur; cur = cur->next) {
+      const char *function_name = cur->info.function;
+      if (!function_name) {
+        continue;
+      }
+      // Match suppressions.
+      Suppression *s;
+      if (suppression_ctx->Match(function_name, suppression, &s)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool IsAllocDeallocMismatchSuppressed(const StackTrace *stack) {
+  CHECK(suppression_ctx);
+  // Match "alloc_dealloc_mismatch" suppressions.
+  return suppression_ctx->HasSuppressionType(kAllocDeallocMismatch) &&
+         IsStackTraceSuppressedByFunction(kAllocDeallocMismatch, stack);
+}
+
 bool IsStackTraceSuppressed(const StackTrace *stack) {
   if (!HaveStackTraceBasedSuppressions())
     return false;
@@ -80,19 +113,9 @@ bool IsStackTraceSuppressed(const StackTrace *stack) {
     }
 
     if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) {
-      SymbolizedStackHolder symbolized_stack(symbolizer->SymbolizePC(addr));
-      const SymbolizedStack *frames = symbolized_stack.get();
-      CHECK(frames);
-      for (const SymbolizedStack *cur = frames; cur; cur = cur->next) {
-        const char *function_name = cur->info.function;
-        if (!function_name) {
-          continue;
-        }
-        // Match "interceptor_via_fun" suppressions.
-        if (suppression_ctx->Match(function_name, kInterceptorViaFunction,
-                                   &s)) {
-          return true;
-        }
+      // Match "interceptor_via_func" suppressions.
+      if (IsStackTraceSuppressedByFunction(kInterceptorViaFunction, stack)) {
+        return true;
       }
     }
   }
diff --git a/compiler-rt/lib/asan/asan_suppressions.h b/compiler-rt/lib/asan/asan_suppressions.h
index 121d4ddf18756e..4613a362f28e45 100644
--- a/compiler-rt/lib/asan/asan_suppressions.h
+++ b/compiler-rt/lib/asan/asan_suppressions.h
@@ -23,6 +23,7 @@ bool IsInterceptorSuppressed(const char *interceptor_name);
 bool HaveStackTraceBasedSuppressions();
 bool IsStackTraceSuppressed(const StackTrace *stack);
 bool IsODRViolationSuppressed(const char *global_var_name);
+bool IsAllocDeallocMismatchSuppressed(const StackTrace *stack);
 
 } // namespace __asan
 
diff --git a/compiler-rt/test/asan/TestCases/suppressions-alloc-dealloc-mismatch.cpp b/compiler-rt/test/asan/TestCases/suppressions-alloc-dealloc-mismatch.cpp
new file mode 100644
index 00000000000000..fe88a5d0c9bf15
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/suppressions-alloc-dealloc-mismatch.cpp
@@ -0,0 +1,26 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// RUN: echo "alloc_dealloc_mismatch:function" > %t.supp
+// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+// RUN: %clangxx_asan -O3 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void function() {
+  char *a = (char *)malloc(6);
+  a[0] = '\0';
+  size_t len = strlen(a);
+  delete a; // BOOM
+  fprintf(stderr, "strlen ignored, len = %zu\n", len);
+}
+
+int main() { function(); }
+
+// CHECK-CRASH: AddressSanitizer: alloc-dealloc-mismatch
+// CHECK-CRASH-NOT: strlen ignored
+// CHECK-IGNORE-NOT: AddressSanitizer: alloc-dealloc-mismatch
+// CHECK-IGNORE: strlen ignored



More information about the llvm-commits mailing list