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

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 07:50:03 PDT 2026


https://github.com/maflcko updated https://github.com/llvm/llvm-project/pull/206735

>From 36f97626f82604a9de89018c43c69270cbacd8f2 Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Mon, 13 Jul 2026 14:00:54 +0200
Subject: [PATCH 1/4] compiler-rt: ubsan: Fix suppressions for inlined
 functions

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.
---
 compiler-rt/lib/ubsan/ubsan_diag.cpp                       | 6 ++++++
 .../ubsan/TestCases/Integer/suppressions-nested-calls.c    | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cpp b/compiler-rt/lib/ubsan/ubsan_diag.cpp
index 6efd082a89934..d06af776b54e1 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cpp
@@ -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) ||
diff --git a/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c b/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c
index 487d35eaa83f4..65b363bb5f9ae 100644
--- a/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c
+++ b/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c
@@ -4,6 +4,7 @@
 // # Test for UBSan suppressions with nested function calls
 //
 // RUN: %clang -fsanitize=integer -O0 -g %s -o %t.o0
+// RUN: %clang -fsanitize=integer -O1 -g %s -o %t.o1
 //
 // # Only the directly suppressed my_make_signed hit should disappear.
 // RUN: echo "implicit-integer-sign-change:my_make_signed" > %t.make_signed.name.supp
@@ -11,6 +12,8 @@
 //
 // 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.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
 //
 // # Only the suppressed wrapper-originated hit should disappear.
 // RUN: echo "implicit-integer-sign-change:my_wrapper_2" > %t.my_wrapper_2.name.supp
@@ -18,6 +21,8 @@
 //
 // 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.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
 //
 // # Suppress both.
 // RUN: cat %t.make_signed.name.supp %t.my_wrapper_2.name.supp > %t.both.name.supp
@@ -25,6 +30,8 @@
 //
 // 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: %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"

>From 944951756b58790b3b27bfaac12c7960f75f9a5d Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Mon, 13 Jul 2026 16:27:13 +0200
Subject: [PATCH 2/4] fix Windows test failure

---
 compiler-rt/lib/ubsan/ubsan_diag.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cpp b/compiler-rt/lib/ubsan/ubsan_diag.cpp
index d06af776b54e1..6a2fcad3e58da 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cpp
@@ -438,9 +438,10 @@ 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.
+#if !SANITIZER_WINDOWS
+  // On POSIX targets, PC is the return address from the UBSan handler call.
   PC = StackTrace::GetPreviousInstructionPc(PC);
+#endif
   const char *SuppType = ConvertTypeToFlagName(ET);
   // Fast path: don't symbolize PC if there is no suppressions for given UB
   // type.

>From 653b4d598eb5bbcf8c20ff5dbd55515aef5dbfff Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Mon, 13 Jul 2026 16:49:12 +0200
Subject: [PATCH 3/4] Revert "fix Windows test failure"

This reverts commit 944951756b58790b3b27bfaac12c7960f75f9a5d.
---
 compiler-rt/lib/ubsan/ubsan_diag.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cpp b/compiler-rt/lib/ubsan/ubsan_diag.cpp
index 6a2fcad3e58da..d06af776b54e1 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cpp
@@ -438,10 +438,9 @@ bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
 bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) {
   InitAsStandaloneIfNecessary();
   CHECK(suppression_ctx);
-#if !SANITIZER_WINDOWS
-  // On POSIX targets, PC is the return address from the UBSan handler call.
+  // PC is the return address from the UBSan handler call. Symbolize the
+  // instruction that caused the call.
   PC = StackTrace::GetPreviousInstructionPc(PC);
-#endif
   const char *SuppType = ConvertTypeToFlagName(ET);
   // Fast path: don't symbolize PC if there is no suppressions for given UB
   // type.

>From f5ebe61cc7683aec6af44cc3760887481c979f83 Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Mon, 13 Jul 2026 16:49:17 +0200
Subject: [PATCH 4/4] Revert "compiler-rt: ubsan: Fix suppressions for inlined
 functions"

This reverts commit 36f97626f82604a9de89018c43c69270cbacd8f2.
---
 compiler-rt/lib/ubsan/ubsan_diag.cpp                       | 6 ------
 .../ubsan/TestCases/Integer/suppressions-nested-calls.c    | 7 -------
 2 files changed, 13 deletions(-)

diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cpp b/compiler-rt/lib/ubsan/ubsan_diag.cpp
index d06af776b54e1..6efd082a89934 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cpp
@@ -438,9 +438,6 @@ 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.
@@ -456,9 +453,6 @@ 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) ||
diff --git a/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c b/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c
index 65b363bb5f9ae..487d35eaa83f4 100644
--- a/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c
+++ b/compiler-rt/test/ubsan/TestCases/Integer/suppressions-nested-calls.c
@@ -4,7 +4,6 @@
 // # Test for UBSan suppressions with nested function calls
 //
 // RUN: %clang -fsanitize=integer -O0 -g %s -o %t.o0
-// RUN: %clang -fsanitize=integer -O1 -g %s -o %t.o1
 //
 // # Only the directly suppressed my_make_signed hit should disappear.
 // RUN: echo "implicit-integer-sign-change:my_make_signed" > %t.make_signed.name.supp
@@ -12,8 +11,6 @@
 //
 // 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.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
 //
 // # Only the suppressed wrapper-originated hit should disappear.
 // RUN: echo "implicit-integer-sign-change:my_wrapper_2" > %t.my_wrapper_2.name.supp
@@ -21,8 +18,6 @@
 //
 // 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.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
 //
 // # Suppress both.
 // RUN: cat %t.make_signed.name.supp %t.my_wrapper_2.name.supp > %t.both.name.supp
@@ -30,8 +25,6 @@
 //
 // 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: %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"



More information about the llvm-commits mailing list