[compiler-rt][ubsan] Fix suppressions for inlined functions (#206735)

Align suppression PC handling with getCallerLocation(), so function
suppressions identify the inlined function that caused a report.

Intentionally match only the innermost inline frame.

Extend suppressions-nested-calls.c coverage to -O1.

Fixes https://github.com/llvm/llvm-project/issues/209501

---------

Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
(cherry picked from commit a376783e2e)
This commit is contained in:
maflcko 2026-07-17 07:42:16 +02:00 committed by Douglas Yung
parent 033aa122e3
commit 52cbf59a50
No known key found for this signature in database
GPG key ID: 316C56D064CACBA5
2 changed files with 21 additions and 7 deletions

View file

@ -438,6 +438,9 @@ bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) {
InitAsStandaloneIfNecessary();
CHECK(suppression_ctx);
// PC is the return address from the UBSan handler call. Symbolize the
// instruction that caused the call.
PC = StackTrace::GetPreviousInstructionPc(PC);
const char *SuppType = ConvertTypeToFlagName(ET);
// Fast path: don't symbolize PC if there is no suppressions for given UB
// type.
@ -453,6 +456,9 @@ bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) {
return true;
}
// Suppress by function or source file name from debug info.
// The first frame is the innermost logical inline frame, if inline debug
// information is available. Do not search the rest of the chain: a
// suppression for an inline wrapper must not suppress an inlined callee.
SymbolizedStackHolder Stack(Symbolizer::GetOrInit()->SymbolizePC(PC));
const AddressInfo &AI = Stack.get()->info;
return suppression_ctx->Match(AI.function, SuppType, &s) ||

View file

@ -3,28 +3,36 @@
// # Test for UBSan suppressions with nested function calls
//
// RUN: %clang -fsanitize=integer -O0 -g %s -o %t.o0
//
// # Only the directly suppressed my_make_signed hit should disappear.
// RUN: echo "implicit-integer-sign-change:my_make_signed" > %t.make_signed.name.supp
// RUN: echo "implicit-integer-sign-change:Inputs/make_signed.h" > %t.make_signed.file.supp
//
// RUN: %env_ubsan_opts=suppressions='"%t.make_signed.name.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-MAKE-SIGNED
// RUN: %env_ubsan_opts=suppressions='"%t.make_signed.file.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-MAKE-SIGNED
//
// # Only the suppressed wrapper-originated hit should disappear.
// RUN: echo "implicit-integer-sign-change:my_wrapper_2" > %t.my_wrapper_2.name.supp
// RUN: echo "implicit-integer-sign-change:Inputs/wrappers.h" > %t.wrappers.file.supp
//
// RUN: %env_ubsan_opts=suppressions='"%t.my_wrapper_2.name.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-WRAPPERS
// RUN: %env_ubsan_opts=suppressions='"%t.wrappers.file.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-WRAPPERS
//
// # Suppress both.
// RUN: cat %t.make_signed.name.supp %t.my_wrapper_2.name.supp > %t.both.name.supp
// RUN: cat %t.make_signed.file.supp %t.wrappers.file.supp > %t.both.file.supp
//
// # Compile and test each optimization level before the next compile. On
// # Windows, the linker emits shared debug and auxiliary-file names here.
// RUN: %clang -fsanitize=integer -O0 -g %s -o %t.o0
// RUN: %env_ubsan_opts=suppressions='"%t.make_signed.name.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-MAKE-SIGNED
// RUN: %env_ubsan_opts=suppressions='"%t.make_signed.file.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-MAKE-SIGNED
// RUN: %env_ubsan_opts=suppressions='"%t.my_wrapper_2.name.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-WRAPPERS
// RUN: %env_ubsan_opts=suppressions='"%t.wrappers.file.supp"' %run %t.o0 2>&1 | FileCheck %s --check-prefix=CHECK-WRAPPERS
// RUN: %env_ubsan_opts=suppressions='"%t.both.name.supp"' %run %t.o0 2>&1 | FileCheck %s --allow-empty --check-prefix=CHECK-BOTH
// RUN: %env_ubsan_opts=suppressions='"%t.both.file.supp"' %run %t.o0 2>&1 | FileCheck %s --allow-empty --check-prefix=CHECK-BOTH
//
// RUN: %clang -fsanitize=integer -O1 -g %s -o %t.o1
// RUN: %env_ubsan_opts=suppressions='"%t.make_signed.name.supp"' %run %t.o1 2>&1 | FileCheck %s --check-prefix=CHECK-MAKE-SIGNED
// RUN: %env_ubsan_opts=suppressions='"%t.make_signed.file.supp"' %run %t.o1 2>&1 | FileCheck %s --check-prefix=CHECK-MAKE-SIGNED
// RUN: %env_ubsan_opts=suppressions='"%t.my_wrapper_2.name.supp"' %run %t.o1 2>&1 | FileCheck %s --check-prefix=CHECK-WRAPPERS
// RUN: %env_ubsan_opts=suppressions='"%t.wrappers.file.supp"' %run %t.o1 2>&1 | FileCheck %s --check-prefix=CHECK-WRAPPERS
// RUN: %env_ubsan_opts=suppressions='"%t.both.name.supp"' %run %t.o1 2>&1 | FileCheck %s --allow-empty --check-prefix=CHECK-BOTH
// RUN: %env_ubsan_opts=suppressions='"%t.both.file.supp"' %run %t.o1 2>&1 | FileCheck %s --allow-empty --check-prefix=CHECK-BOTH
#include "Inputs/make_signed.h"
#include "Inputs/wrappers.h"