mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-21 10:16:49 +00:00
[sanitizer] Support "alloc_dealloc_mismatch" suppressions (#124197)
This adds a stack-based suppression for alloc-dealloc-mismatch violations, using the function name to match.
This commit is contained in:
parent
98d6dd3988
commit
6b654a09c2
compiler-rt
lib/asan
test/asan/TestCases
@ -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);
|
||||
}
|
||||
|
@ -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,44 @@ bool IsODRViolationSuppressed(const char *global_var_name) {
|
||||
return suppression_ctx->Match(global_var_name, kODRViolation, &s);
|
||||
}
|
||||
|
||||
bool IsAddrSuppressed(const char *suppression, Symbolizer *symbolizer,
|
||||
uptr addr) {
|
||||
CHECK(suppression_ctx);
|
||||
CHECK(suppression_ctx->HasSuppressionType(suppression));
|
||||
CHECK(symbolizer);
|
||||
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.
|
||||
Suppression *s;
|
||||
if (suppression_ctx->Match(function_name, suppression, &s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAllocDeallocMismatchSuppressed(const StackTrace *stack) {
|
||||
CHECK(suppression_ctx);
|
||||
if (!suppression_ctx->HasSuppressionType(kAllocDeallocMismatch)) {
|
||||
return false;
|
||||
}
|
||||
Symbolizer *symbolizer = Symbolizer::GetOrInit();
|
||||
for (uptr i = 0; i < stack->size && stack->trace[i]; i++) {
|
||||
uptr addr = stack->trace[i];
|
||||
// Match "alloc_dealloc_mismatch" suppressions.
|
||||
if (IsAddrSuppressed(kAllocDeallocMismatch, symbolizer, addr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsStackTraceSuppressed(const StackTrace *stack) {
|
||||
if (!HaveStackTraceBasedSuppressions())
|
||||
return false;
|
||||
@ -80,19 +119,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 (IsAddrSuppressed(kInterceptorViaFunction, symbolizer, addr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user