[compiler-rt] [sanitizer] Support "alloc_dealloc_mismatch" suppressions (PR #124197)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 23 13:45:34 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: None (andrewjcg)
<details>
<summary>Changes</summary>
This adds a stack-based suppression for alloc-dealloc-mismatch violations, using the function name to match.
---
Full diff: https://github.com/llvm/llvm-project/pull/124197.diff
3 Files Affected:
- (modified) compiler-rt/lib/asan/asan_allocator.cpp (+3-1)
- (modified) compiler-rt/lib/asan/asan_suppressions.cpp (+20-15)
- (added) compiler-rt/test/asan/TestCases/suppressions-alloc-dealloc-mismatch.cpp (+35)
``````````diff
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 9e66f77217ec6b..a5f939b4c2f8aa 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) &&
+ !IsStackTraceSuppressed(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..f45b5cf611b59b 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 "";
@@ -52,7 +53,8 @@ bool IsInterceptorSuppressed(const char *interceptor_name) {
bool HaveStackTraceBasedSuppressions() {
CHECK(suppression_ctx);
return suppression_ctx->HasSuppressionType(kInterceptorViaFunction) ||
- suppression_ctx->HasSuppressionType(kInterceptorViaLibrary);
+ suppression_ctx->HasSuppressionType(kInterceptorViaLibrary) ||
+ suppression_ctx->HasSuppressionType(kAllocDeallocMismatch);
}
bool IsODRViolationSuppressed(const char *global_var_name) {
@@ -79,19 +81,22 @@ bool IsStackTraceSuppressed(const StackTrace *stack) {
return true;
}
- 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;
+ const char *suppressions[] = {kInterceptorViaFunction,
+ kAllocDeallocMismatch};
+ for (const char *suppression : suppressions) {
+ if (suppression_ctx->HasSuppressionType(suppression)) {
+ 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 suppressions.
+ if (suppression_ctx->Match(function_name, suppression, &s)) {
+ return true;
+ }
}
}
}
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..47b99a090beddd
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/suppressions-alloc-dealloc-mismatch.cpp
@@ -0,0 +1,35 @@
+// 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
+
+// XFAIL: android
+// UNSUPPORTED: ios
+
+// FIXME: atos does not work for inlined functions, yet llvm-symbolizer
+// does not always work with debug info on Darwin.
+// UNSUPPORTED: darwin
+
+#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
``````````
</details>
https://github.com/llvm/llvm-project/pull/124197
More information about the llvm-commits
mailing list