[clang] [Clang] Implement labelled type filtering for overflow/truncation sanitizers w/ SSCLs (PR #107332)

Justin Stitt via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 31 13:24:07 PDT 2024


https://github.com/JustinStitt updated https://github.com/llvm/llvm-project/pull/107332

>From 548efc6414503f8ae005f1bd9ef2c7f15ad16241 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Tue, 3 Sep 2024 18:28:53 -0700
Subject: [PATCH 01/12] hook up sscl categories with overflow/truncation
 sanitizers

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/include/clang/AST/ASTContext.h         |  3 +
 clang/lib/AST/ASTContext.cpp                 | 31 +++++++
 clang/lib/CodeGen/CGExprScalar.cpp           | 36 +++++++-
 clang/test/CodeGen/ubsan-type-ignorelist.cpp | 88 +++++++++++++++++---
 4 files changed, 144 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 1984310df0442e..44878d74499f66 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -830,6 +830,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   const NoSanitizeList &getNoSanitizeList() const { return *NoSanitizeL; }
 
+  bool isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
+                                const QualType &Ty) const;
+
   const XRayFunctionFilter &getXRayFilter() const {
     return *XRayFilter;
   }
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index fd8aa8de79b49f..4270ddc90b7b24 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -831,6 +831,37 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
   return CanonTTP;
 }
 
+/// Check if a type can have its sanitizer instrumentation elided.
+/// Determine this by its presence in a SCL alongside its specified categories.
+/// For example:
+/// ignorelist.txt>
+/// [{unsigned-integer-overflow,signed-integer-overflow}]
+/// type:*
+/// type:size_t=skip
+/// <ignorelist.txt
+/// Supplying the above ignorelist.txt will disable overflow sanitizer
+/// instrumentation for all types except "size_t".
+bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
+                                          const QualType &Ty) const {
+  // One may specifically allow a type "type:foo=allow"
+  bool isAllowedBySCL =
+      NoSanitizeL->containsType(Mask, Ty.getAsString(), "allow");
+
+  // There could also be no category present "type:foo", which is the same as
+  // "allow"
+  isAllowedBySCL |= NoSanitizeL->containsType(Mask, Ty.getAsString());
+
+  // Explicitly specifying "skip" is also possible "type:foo=skip"
+  bool isSkippedBySCL =
+      NoSanitizeL->containsType(Mask, Ty.getAsString(), "skip");
+
+  // Or "forbid", as there is currently no distinction between "skip" and
+  // "forbid" for the purposes of the overflow/truncation sanitizer ignorelist.
+  isSkippedBySCL |= NoSanitizeL->containsType(Mask, Ty.getAsString(), "forbid");
+
+  return isAllowedBySCL && !isSkippedBySCL;
+}
+
 TargetCXXABI::Kind ASTContext::getCXXABIKind() const {
   auto Kind = getTargetInfo().getCXXABI().getKind();
   return getLangOpts().CXXABI.value_or(Kind);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index b7f5b932c56b6f..bc19813a04e42f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -197,6 +197,18 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
   if (!Op.mayHaveIntegerOverflow())
     return true;
 
+  if (Op.Ty->isSignedIntegerType() &&
+      Ctx.isTypeIgnoredBySanitizer(SanitizerKind::SignedIntegerOverflow,
+                                   Op.Ty)) {
+    return true;
+  }
+
+  if (Op.Ty->isUnsignedIntegerType() &&
+      Ctx.isTypeIgnoredBySanitizer(SanitizerKind::UnsignedIntegerOverflow,
+                                   Op.Ty)) {
+    return true;
+  }
+
   const UnaryOperator *UO = dyn_cast<UnaryOperator>(Op.E);
 
   if (UO && UO->getOpcode() == UO_Minus &&
@@ -1121,6 +1133,10 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
   if (!CGF.SanOpts.has(Check.second.second))
     return;
 
+  // Does some SSCL ignore this type?
+  if (CGF.getContext().isTypeIgnoredBySanitizer(Check.second.second, DstType))
+    return;
+
   llvm::Constant *StaticArgs[] = {
       CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
       CGF.EmitCheckTypeDescriptor(DstType),
@@ -1231,6 +1247,15 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
     // Because here sign change check is interchangeable with truncation check.
     return;
   }
+  // Does an SSCL have an entry for the DstType under its respective sanitizer
+  // section?
+  if (DstSigned && CGF.getContext().isTypeIgnoredBySanitizer(
+                       SanitizerKind::ImplicitSignedIntegerTruncation, DstType))
+    return;
+  if (!DstSigned &&
+      CGF.getContext().isTypeIgnoredBySanitizer(
+          SanitizerKind::ImplicitUnsignedIntegerTruncation, DstType))
+    return;
   // That's it. We can't rule out any more cases with the data we have.
 
   CodeGenFunction::SanitizerScope SanScope(&CGF);
@@ -2780,10 +2805,11 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
       return Builder.CreateNSWAdd(InVal, Amount, Name);
     [[fallthrough]];
   case LangOptions::SOB_Trapping:
-    if (!E->canOverflow())
+    BinOpInfo Info = createBinOpInfoFromIncDec(
+        E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts()));
+    if (!E->canOverflow() || CanElideOverflowCheck(CGF.getContext(), Info))
       return Builder.CreateNSWAdd(InVal, Amount, Name);
-    return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
-        E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
+    return EmitOverflowCheckedBinOp(Info);
   }
   llvm_unreachable("Unknown SignedOverflowBehaviorTy");
 }
@@ -2986,7 +3012,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
       value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
     } else if (E->canOverflow() && type->isUnsignedIntegerType() &&
                CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
-               !excludeOverflowPattern) {
+               !excludeOverflowPattern &&
+               !CGF.getContext().isTypeIgnoredBySanitizer(
+                   SanitizerKind::UnsignedIntegerOverflow, E->getType())) {
       value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
           E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
     } else {
diff --git a/clang/test/CodeGen/ubsan-type-ignorelist.cpp b/clang/test/CodeGen/ubsan-type-ignorelist.cpp
index 7bea84f5fabb93..2364b692e53160 100644
--- a/clang/test/CodeGen/ubsan-type-ignorelist.cpp
+++ b/clang/test/CodeGen/ubsan-type-ignorelist.cpp
@@ -1,23 +1,91 @@
+// Verify ubsan doesn't emit checks for ignorelisted types
+// RUN: echo "[{unsigned-integer-overflow,signed-integer-overflow}]" > %t-int.ignorelist
+// RUN: echo "type:int" >> %t-int.ignorelist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-int.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=INT
+
+// RUN: echo "type:int" > %t-nosection.ignorelist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-nosection.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=INT
+
+// RUN: echo "type:int=allow" > %t-allow-same-as-no-category.ignorelist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-allow-same-as-no-category.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=INT
+
+// RUN: echo "[{unsigned-integer-overflow,signed-integer-overflow}]" > %t-myty.ignorelist
+// RUN: echo "type:*" >> %t-myty.ignorelist
+// RUN: echo "type:myty=skip" >> %t-myty.ignorelist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-myty.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=MYTY
+
+// RUN: echo "[{implicit-signed-integer-truncation,implicit-unsigned-integer-truncation}]" > %t-trunc.ignorelist
+// RUN: echo "type:char" >> %t-trunc.ignorelist
+// RUN: echo "type:unsigned char" >> %t-trunc.ignorelist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t-trunc.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=TRUNC
+
 // Verify ubsan vptr does not check down-casts on ignorelisted types.
 // RUN: echo "type:_ZTI3Foo" > %t-type.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t-type.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=VPTR
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t-type.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=VPTR-TYPE
 
 class Bar {
-public:
-  virtual ~Bar() {}
+  public:
+    virtual ~Bar() {}
 };
 class Foo : public Bar {};
 
 Bar bar;
 
-// DEFAULT: @_Z7checkmev
-// TYPE: @_Z7checkmev
+// VPTR: @_Z7checkmev
+// VPTR-TYPE: @_Z7checkmev
 void checkme() {
-// DEFAULT: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (ptr @bar to
-// TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
+  // VPTR: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (ptr @bar to
+  // VPTR-TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
   Foo* foo = static_cast<Foo*>(&bar); // down-casting
-// DEFAULT: ret void
-// TYPE: ret void
+                                      // VPTR: ret void
+                                      // VPTR-TYPE: ret void
   return;
 }
+
+// INT-LABEL: ignore_int
+void ignore_int(int A, int B, unsigned C, unsigned D, long E) {
+  // INT: llvm.uadd.with.overflow.i32
+  (void)(C+D);
+  // INT-NOT: llvm.sadd.with.overflow.i32
+  (void)(A+B);
+  // INT: llvm.sadd.with.overflow.i64
+  (void)(++E);
+}
+
+
+typedef unsigned long myty;
+typedef myty derivative;
+// INT-LABEL: ignore_all_except_myty
+// MYTY-LABEL: ignore_all_except_myty
+void ignore_all_except_myty(myty A, myty B, int C, unsigned D, derivative E) {
+  // MYTY-NOT: llvm.sadd.with.overflow.i32
+  (void)(++C);
+
+  // MYTY-NOT: llvm.uadd.with.overflow.i32
+  (void)(D+D);
+
+  // MYTY-NOT: llvm.umul.with.overflow.i64
+  (void)(E*2);
+
+  // MYTY: llvm.uadd.with.overflow.i64
+  (void)(A+B);
+}
+
+// INT-LABEL: truncation
+// MYTY-LABEL: truncation
+// TRUNC-LABEL: truncation
+void truncation(char A, int B, unsigned char C, short D) {
+  // TRUNC-NOT: %handler.implicit_conversion
+  A = B;
+  // TRUNC-NOT: %handler.implicit_conversion
+  A = C;
+  // TRUNC-NOT: %handler.implicit_conversion
+  C = B;
+
+  // TRUNC: %handler.implicit_conversion
+  D = B;
+
+  (void)A;
+  (void)D;
+}

>From 6efbd7b17ca247ddeef1a261c3813df6516bac23 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 4 Sep 2024 15:43:21 -0700
Subject: [PATCH 02/12] add docs

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/docs/ReleaseNotes.rst             |  8 ++++
 clang/docs/SanitizerSpecialCaseList.rst | 62 ++++++++++++++++++++++++-
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 14907e7db18de3..1051dde3b7ef47 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -635,6 +635,14 @@ Sanitizers
   This new flag should allow those projects to enable integer sanitizers with
   less noise.
 
+- Arithmetic overflow sanitizers ``-fsanitize=signed-integer-overflow`` and
+  ``-fsanitize=unsigned-integer-overflow`` as well as the implicit integer
+  truncation sanitizers ``-fsanitize=implicit-signed-integer-truncation`` and
+  ``-fsanitize=implicit-unsigned-integer-truncation`` now properly support the
+  "type" prefix within `Sanitizer Special Case Lists (SSCL)
+  <https://clang.llvm.org/docs/SanitizerSpecialCaseList.html>`_. See that link
+  for examples.
+
 Python Binding Changes
 ----------------------
 - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.
diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index c7fb0fa3f8a828..13f71b878d4cc8 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -15,8 +15,9 @@ file at compile-time.
 Goal and usage
 ==============
 
-Users of sanitizer tools, such as :doc:`AddressSanitizer`, :doc:`ThreadSanitizer`
-or :doc:`MemorySanitizer` may want to disable or alter some checks for
+Users of sanitizer tools, such as :doc:`AddressSanitizer`,
+:doc:`ThreadSanitizer`, :doc:`MemorySanitizer` or :doc:
+`UndefinedBehaviorSanitizer` may want to disable or alter some checks for
 certain source-level entities to:
 
 * speedup hot function, which is known to be correct;
@@ -48,6 +49,63 @@ Example
   $ clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
   # No error report here.
 
+Usage with UndefinedBehaviorSanitizer
+=====================================
+
+The arithmetic overflow sanitizers ``unsigned-integer-overflow`` and
+``signed-integer-overflow`` as well as the implicit integer truncation
+sanitizers ``implicit-signed-integer-truncation`` and
+``implicit-unsigned-integer-truncation`` support the ability to adjust
+instrumentation based on type.
+
+.. code-block:: bash
+
+  $ cat foo.c
+  void foo() {
+    int a = 2147483647; // INT_MAX
+    ++a;                // Normally, an overflow with -fsanitize=signed-integer-overflow
+  }
+  $ cat ignorelist.txt
+  [signed-integer-overflow]
+  type:int
+  $ clang -fsanitize=signed-integer-overflow -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
+  # no signed-integer-overflow error
+
+Supplying ``ignorelist.txt`` with ``-fsanitize-ignorelist=ignorelist.txt``
+disables overflow sanitizer instrumentation for arithmetic operations
+containing values of type ``int``, for example. Custom types may be used.
+
+The following SCL categories are supported: ``=allow``, ``=skip`` and
+``=forbid``. The ``allow`` category is the default for any entry and specifies
+that the query, if matched, will have its sanitizer instrumentation ignored.
+Conversely, both ``skip`` and ``forbid`` cause their queries, if matched, to be
+left out of the ignorelist -- essentially ensuring sanitizer instrumentation
+remains for those types. This is useful for whitelisting specific types.
+
+With this, one may disable instrumentation for all types and specifically allow
+instrumentation for one or many types.
+
+.. code-block:: bash
+
+  $ cat ignorelist.txt
+  [implicit-signed-integer-truncation]
+  type:*=allow
+  type:T=skip
+  $ cat foo.c
+  typedef char T;
+  typedef char U;
+  void foo(int toobig) {
+    T a = toobig;    // instrumented
+    U b = toobig;    // not instrumented
+    char c = toobig; // also not instrumented
+  }
+
+Note that ``skip`` and ``forbid`` operate exactly the same in this context and
+both options exist simply for conformity with the `-fprofile-list
+<https://clang.llvm.org/docs/UsersManual.html#instrumenting-only-selected-files-or-functions>`_
+syntax for adjusting profile instrumentation. You do not need to specify any
+`default:<type>` for ``-fsanitize-ignorelist`` SSCLs, though.
+
 Format
 ======
 

>From 21be60a590141896713536941f2d3db5f8508733 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 4 Sep 2024 16:53:35 -0700
Subject: [PATCH 03/12] fix formatting on docs

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/test/CodeGen/ubsan-type-ignorelist.cpp | 34 ++++++++++----------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/clang/test/CodeGen/ubsan-type-ignorelist.cpp b/clang/test/CodeGen/ubsan-type-ignorelist.cpp
index 2364b692e53160..e8b14d5c415222 100644
--- a/clang/test/CodeGen/ubsan-type-ignorelist.cpp
+++ b/clang/test/CodeGen/ubsan-type-ignorelist.cpp
@@ -25,8 +25,8 @@
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t-type.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=VPTR-TYPE
 
 class Bar {
-  public:
-    virtual ~Bar() {}
+public:
+  virtual ~Bar() {}
 };
 class Foo : public Bar {};
 
@@ -35,21 +35,21 @@ Bar bar;
 // VPTR: @_Z7checkmev
 // VPTR-TYPE: @_Z7checkmev
 void checkme() {
-  // VPTR: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (ptr @bar to
-  // VPTR-TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
+// VPTR: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (ptr @bar to
+// VPTR-TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
   Foo* foo = static_cast<Foo*>(&bar); // down-casting
-                                      // VPTR: ret void
-                                      // VPTR-TYPE: ret void
+// VPTR: ret void
+// VPTR-TYPE: ret void
   return;
 }
 
 // INT-LABEL: ignore_int
 void ignore_int(int A, int B, unsigned C, unsigned D, long E) {
-  // INT: llvm.uadd.with.overflow.i32
+// INT: llvm.uadd.with.overflow.i32
   (void)(C+D);
-  // INT-NOT: llvm.sadd.with.overflow.i32
+// INT-NOT: llvm.sadd.with.overflow.i32
   (void)(A+B);
-  // INT: llvm.sadd.with.overflow.i64
+// INT: llvm.sadd.with.overflow.i64
   (void)(++E);
 }
 
@@ -59,16 +59,16 @@ typedef myty derivative;
 // INT-LABEL: ignore_all_except_myty
 // MYTY-LABEL: ignore_all_except_myty
 void ignore_all_except_myty(myty A, myty B, int C, unsigned D, derivative E) {
-  // MYTY-NOT: llvm.sadd.with.overflow.i32
+// MYTY-NOT: llvm.sadd.with.overflow.i32
   (void)(++C);
 
-  // MYTY-NOT: llvm.uadd.with.overflow.i32
+// MYTY-NOT: llvm.uadd.with.overflow.i32
   (void)(D+D);
 
-  // MYTY-NOT: llvm.umul.with.overflow.i64
+// MYTY-NOT: llvm.umul.with.overflow.i64
   (void)(E*2);
 
-  // MYTY: llvm.uadd.with.overflow.i64
+// MYTY: llvm.uadd.with.overflow.i64
   (void)(A+B);
 }
 
@@ -76,14 +76,14 @@ void ignore_all_except_myty(myty A, myty B, int C, unsigned D, derivative E) {
 // MYTY-LABEL: truncation
 // TRUNC-LABEL: truncation
 void truncation(char A, int B, unsigned char C, short D) {
-  // TRUNC-NOT: %handler.implicit_conversion
+// TRUNC-NOT: %handler.implicit_conversion
   A = B;
-  // TRUNC-NOT: %handler.implicit_conversion
+// TRUNC-NOT: %handler.implicit_conversion
   A = C;
-  // TRUNC-NOT: %handler.implicit_conversion
+// TRUNC-NOT: %handler.implicit_conversion
   C = B;
 
-  // TRUNC: %handler.implicit_conversion
+// TRUNC: %handler.implicit_conversion
   D = B;
 
   (void)A;

>From ce2a8086ad113cec0d6d6bd5c7077fe120f6db03 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 25 Sep 2024 12:25:36 -0700
Subject: [PATCH 04/12] use split-file for tests

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 ...orelist.cpp => ubsan-type-ignorelist.test} | 52 ++++++++++++-------
 1 file changed, 33 insertions(+), 19 deletions(-)
 rename clang/test/CodeGen/{ubsan-type-ignorelist.cpp => ubsan-type-ignorelist.test} (64%)

diff --git a/clang/test/CodeGen/ubsan-type-ignorelist.cpp b/clang/test/CodeGen/ubsan-type-ignorelist.test
similarity index 64%
rename from clang/test/CodeGen/ubsan-type-ignorelist.cpp
rename to clang/test/CodeGen/ubsan-type-ignorelist.test
index e8b14d5c415222..14f297fcec2065 100644
--- a/clang/test/CodeGen/ubsan-type-ignorelist.cpp
+++ b/clang/test/CodeGen/ubsan-type-ignorelist.test
@@ -1,29 +1,43 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
 // Verify ubsan doesn't emit checks for ignorelisted types
-// RUN: echo "[{unsigned-integer-overflow,signed-integer-overflow}]" > %t-int.ignorelist
-// RUN: echo "type:int" >> %t-int.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-int.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=INT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/int.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosection.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/allow-same-as-no-category.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/myty.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=MYTY
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/trunc.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC
+
+// Verify ubsan vptr does not check down-casts on ignorelisted types.
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=VPTR
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t/vptr.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=VPTR-TYPE
 
-// RUN: echo "type:int" > %t-nosection.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-nosection.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=INT
 
-// RUN: echo "type:int=allow" > %t-allow-same-as-no-category.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-allow-same-as-no-category.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=INT
+//--- int.ignorelist
+[{unsigned-integer-overflow,signed-integer-overflow}]
+type:int
 
-// RUN: echo "[{unsigned-integer-overflow,signed-integer-overflow}]" > %t-myty.ignorelist
-// RUN: echo "type:*" >> %t-myty.ignorelist
-// RUN: echo "type:myty=skip" >> %t-myty.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t-myty.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=MYTY
+//--- nosection.ignorelist
+type:int
 
-// RUN: echo "[{implicit-signed-integer-truncation,implicit-unsigned-integer-truncation}]" > %t-trunc.ignorelist
-// RUN: echo "type:char" >> %t-trunc.ignorelist
-// RUN: echo "type:unsigned char" >> %t-trunc.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t-trunc.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=TRUNC
+//--- allow-same-as-no-category.ignorelist
+type:int=allow
 
-// Verify ubsan vptr does not check down-casts on ignorelisted types.
-// RUN: echo "type:_ZTI3Foo" > %t-type.ignorelist
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=VPTR
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t-type.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=VPTR-TYPE
+//--- myty.ignorelist
+[{unsigned-integer-overflow,signed-integer-overflow}]
+type:*
+type:myty=skip
+
+//--- trunc.ignorelist
+[{implicit-signed-integer-truncation,implicit-unsigned-integer-truncation}]
+type:char
+type:unsigned char
+
+
+//--- vptr.ignorelist
+type:_ZTI3Foo
 
+//--- test.cpp
 class Bar {
 public:
   virtual ~Bar() {}

>From 7f92e75930d5c69249c636c1e454519211b9a5f2 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 25 Sep 2024 16:17:51 -0700
Subject: [PATCH 05/12] use no_sanitize and sanitize over allow and skip/forbid

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/docs/SanitizerSpecialCaseList.rst       | 23 +++++++----------
 clang/lib/AST/ASTContext.cpp                  | 25 ++++++-------------
 clang/test/CodeGen/ubsan-type-ignorelist.test |  8 +++---
 3 files changed, 21 insertions(+), 35 deletions(-)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index 13f71b878d4cc8..6ca8bb632082e1 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -75,12 +75,13 @@ Supplying ``ignorelist.txt`` with ``-fsanitize-ignorelist=ignorelist.txt``
 disables overflow sanitizer instrumentation for arithmetic operations
 containing values of type ``int``, for example. Custom types may be used.
 
-The following SCL categories are supported: ``=allow``, ``=skip`` and
-``=forbid``. The ``allow`` category is the default for any entry and specifies
-that the query, if matched, will have its sanitizer instrumentation ignored.
-Conversely, both ``skip`` and ``forbid`` cause their queries, if matched, to be
-left out of the ignorelist -- essentially ensuring sanitizer instrumentation
-remains for those types. This is useful for whitelisting specific types.
+The following SCL categories are supported: ``=no_sanitize`` and ``=sanitize``.
+The ``no_sanitize`` category is the default for any entry within an ignorelist
+and specifies that the query, if matched, will have its sanitizer
+instrumentation ignored. Conversely, ``sanitize`` causes its queries, if
+matched, to be left out of the ignorelist -- essentially ensuring sanitizer
+instrumentation remains for those types. This is useful for whitelisting
+specific types.
 
 With this, one may disable instrumentation for all types and specifically allow
 instrumentation for one or many types.
@@ -89,8 +90,8 @@ instrumentation for one or many types.
 
   $ cat ignorelist.txt
   [implicit-signed-integer-truncation]
-  type:*=allow
-  type:T=skip
+  type:*=no_sanitize
+  type:T=sanitize
   $ cat foo.c
   typedef char T;
   typedef char U;
@@ -100,12 +101,6 @@ instrumentation for one or many types.
     char c = toobig; // also not instrumented
   }
 
-Note that ``skip`` and ``forbid`` operate exactly the same in this context and
-both options exist simply for conformity with the `-fprofile-list
-<https://clang.llvm.org/docs/UsersManual.html#instrumenting-only-selected-files-or-functions>`_
-syntax for adjusting profile instrumentation. You do not need to specify any
-`default:<type>` for ``-fsanitize-ignorelist`` SSCLs, though.
-
 Format
 ======
 
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 4270ddc90b7b24..f03bacec83ca7c 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -836,30 +836,21 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
 /// For example:
 /// ignorelist.txt>
 /// [{unsigned-integer-overflow,signed-integer-overflow}]
-/// type:*
-/// type:size_t=skip
+/// type:*=no_sanitize
+/// type:size_t=sanitize
 /// <ignorelist.txt
 /// Supplying the above ignorelist.txt will disable overflow sanitizer
 /// instrumentation for all types except "size_t".
 bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
                                           const QualType &Ty) const {
-  // One may specifically allow a type "type:foo=allow"
-  bool isAllowedBySCL =
-      NoSanitizeL->containsType(Mask, Ty.getAsString(), "allow");
+  bool sanitizeType =
+      NoSanitizeL->containsType(Mask, Ty.getAsString(), "sanitize");
 
-  // There could also be no category present "type:foo", which is the same as
-  // "allow"
-  isAllowedBySCL |= NoSanitizeL->containsType(Mask, Ty.getAsString());
+  bool noSanitizeType =
+      NoSanitizeL->containsType(Mask, Ty.getAsString(), "no_sanitize") ||
+      NoSanitizeL->containsType(Mask, Ty.getAsString());
 
-  // Explicitly specifying "skip" is also possible "type:foo=skip"
-  bool isSkippedBySCL =
-      NoSanitizeL->containsType(Mask, Ty.getAsString(), "skip");
-
-  // Or "forbid", as there is currently no distinction between "skip" and
-  // "forbid" for the purposes of the overflow/truncation sanitizer ignorelist.
-  isSkippedBySCL |= NoSanitizeL->containsType(Mask, Ty.getAsString(), "forbid");
-
-  return isAllowedBySCL && !isSkippedBySCL;
+  return noSanitizeType && !sanitizeType;
 }
 
 TargetCXXABI::Kind ASTContext::getCXXABIKind() const {
diff --git a/clang/test/CodeGen/ubsan-type-ignorelist.test b/clang/test/CodeGen/ubsan-type-ignorelist.test
index 14f297fcec2065..f5762d21548532 100644
--- a/clang/test/CodeGen/ubsan-type-ignorelist.test
+++ b/clang/test/CodeGen/ubsan-type-ignorelist.test
@@ -4,7 +4,7 @@
 // Verify ubsan doesn't emit checks for ignorelisted types
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/int.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosection.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/allow-same-as-no-category.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosan-same-as-no-category.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/myty.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=MYTY
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/trunc.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC
 
@@ -20,13 +20,13 @@ type:int
 //--- nosection.ignorelist
 type:int
 
-//--- allow-same-as-no-category.ignorelist
-type:int=allow
+//--- nosan-same-as-no-category.ignorelist
+type:int=no_sanitize
 
 //--- myty.ignorelist
 [{unsigned-integer-overflow,signed-integer-overflow}]
 type:*
-type:myty=skip
+type:myty=sanitize
 
 //--- trunc.ignorelist
 [{implicit-signed-integer-truncation,implicit-unsigned-integer-truncation}]

>From f119326d87b2646d65636b8101a17a262f7461d7 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 11:00:04 -0700
Subject: [PATCH 06/12] rephrase some documentation for readability's sake

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/docs/SanitizerSpecialCaseList.rst | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index 6ca8bb632082e1..3c3659dd149af0 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -71,9 +71,9 @@ instrumentation based on type.
   $ clang -fsanitize=signed-integer-overflow -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
   # no signed-integer-overflow error
 
-Supplying ``ignorelist.txt`` with ``-fsanitize-ignorelist=ignorelist.txt``
-disables overflow sanitizer instrumentation for arithmetic operations
-containing values of type ``int``, for example. Custom types may be used.
+For example, supplying the above ``ignorelist.txt`` to
+``-fsanitize-ignorelist=ignorelist.txt`` disables overflow sanitizer
+instrumentation for arithmetic operations containing values of type ``int``.
 
 The following SCL categories are supported: ``=no_sanitize`` and ``=sanitize``.
 The ``no_sanitize`` category is the default for any entry within an ignorelist
@@ -84,7 +84,8 @@ instrumentation remains for those types. This is useful for whitelisting
 specific types.
 
 With this, one may disable instrumentation for all types and specifically allow
-instrumentation for one or many types.
+instrumentation for one or many types -- including types created via
+``typedef``.
 
 .. code-block:: bash
 

>From d670482ca0dec24f49e2568351fdd5f42badfb17 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 18:44:55 -0700
Subject: [PATCH 07/12] fix improper link formatting

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/docs/SanitizerSpecialCaseList.rst | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index 3c3659dd149af0..ab1f1954d9bfbe 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -16,9 +16,8 @@ Goal and usage
 ==============
 
 Users of sanitizer tools, such as :doc:`AddressSanitizer`,
-:doc:`ThreadSanitizer`, :doc:`MemorySanitizer` or :doc:
-`UndefinedBehaviorSanitizer` may want to disable or alter some checks for
-certain source-level entities to:
+:doc:`ThreadSanitizer`, :doc:`MemorySanitizer` or :doc:`UndefinedBehaviorSanitizer`
+may want to disable or alter some checks for certain source-level entities to:
 
 * speedup hot function, which is known to be correct;
 * ignore a function that does some low-level magic (e.g. walks through the

>From 8e473070c9045395d627bfece040e7d7985c0943 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 19:59:26 -0700
Subject: [PATCH 08/12] readd removed test

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/test/CodeGen/ubsan-type-ignorelist.cpp | 23 ++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 clang/test/CodeGen/ubsan-type-ignorelist.cpp

diff --git a/clang/test/CodeGen/ubsan-type-ignorelist.cpp b/clang/test/CodeGen/ubsan-type-ignorelist.cpp
new file mode 100644
index 00000000000000..7bea84f5fabb93
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-type-ignorelist.cpp
@@ -0,0 +1,23 @@
+// Verify ubsan vptr does not check down-casts on ignorelisted types.
+// RUN: echo "type:_ZTI3Foo" > %t-type.ignorelist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t-type.ignorelist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE
+
+class Bar {
+public:
+  virtual ~Bar() {}
+};
+class Foo : public Bar {};
+
+Bar bar;
+
+// DEFAULT: @_Z7checkmev
+// TYPE: @_Z7checkmev
+void checkme() {
+// DEFAULT: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (ptr @bar to
+// TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
+  Foo* foo = static_cast<Foo*>(&bar); // down-casting
+// DEFAULT: ret void
+// TYPE: ret void
+  return;
+}

>From 33aa461aeaea6e42aea80745b5bf3fbeab6c5499 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 20:00:18 -0700
Subject: [PATCH 09/12] add new test for category precedence, rename
 pre-existing test

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 .../ubsan-type-ignorelist-category-2.test     | 58 +++++++++++++++++++
 ...st => ubsan-type-ignorelist-category.test} | 28 ---------
 2 files changed, 58 insertions(+), 28 deletions(-)
 create mode 100644 clang/test/CodeGen/ubsan-type-ignorelist-category-2.test
 rename clang/test/CodeGen/{ubsan-type-ignorelist.test => ubsan-type-ignorelist-category.test} (76%)

diff --git a/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test b/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test
new file mode 100644
index 00000000000000..79b506ebdb97ea
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test
@@ -0,0 +1,58 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-0.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-1.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-2.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-3.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-4.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-5.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-6.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-7.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
+
+// The same type can appear multiple times within an ignorelist. This is a test
+// to make sure "=sanitize" has priority regardless of the order in which
+// duplicate type entries appear. This is a precautionary measure; we would
+// much rather eagerly sanitize than silently forgo sanitization.
+
+//--- order-0.ignorelist
+type:int=no_sanitize
+type:int=sanitize
+
+//--- order-1.ignorelist
+type:int=sanitize
+type:int=no_sanitize
+
+//--- order-2.ignorelist
+type:in*=no_sanitize
+type:int=sanitize
+
+//--- order-3.ignorelist
+type:in*=sanitize
+type:int=no_sanitize
+
+//--- order-4.ignorelist
+type:int=no_sanitize
+type:in*=sanitize
+
+//--- order-5.ignorelist
+type:int=sanitize
+type:in*=no_sanitize
+
+//--- order-6.ignorelist
+type:int=sanitize
+type:in*
+
+//--- order-7.ignorelist
+type:int
+type:int=sanitize
+
+
+
+
+//--- test.c
+// CHECK-LABEL: @test
+void test(int A) {
+// CHECK: @llvm.sadd.with.overflow.i32
+  ++A;
+}
diff --git a/clang/test/CodeGen/ubsan-type-ignorelist.test b/clang/test/CodeGen/ubsan-type-ignorelist-category.test
similarity index 76%
rename from clang/test/CodeGen/ubsan-type-ignorelist.test
rename to clang/test/CodeGen/ubsan-type-ignorelist-category.test
index f5762d21548532..795272971de0b5 100644
--- a/clang/test/CodeGen/ubsan-type-ignorelist.test
+++ b/clang/test/CodeGen/ubsan-type-ignorelist-category.test
@@ -8,11 +8,6 @@
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/myty.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=MYTY
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/trunc.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC
 
-// Verify ubsan vptr does not check down-casts on ignorelisted types.
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=VPTR
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-ignorelist=%t/vptr.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=VPTR-TYPE
-
-
 //--- int.ignorelist
 [{unsigned-integer-overflow,signed-integer-overflow}]
 type:int
@@ -33,30 +28,7 @@ type:myty=sanitize
 type:char
 type:unsigned char
 
-
-//--- vptr.ignorelist
-type:_ZTI3Foo
-
 //--- test.cpp
-class Bar {
-public:
-  virtual ~Bar() {}
-};
-class Foo : public Bar {};
-
-Bar bar;
-
-// VPTR: @_Z7checkmev
-// VPTR-TYPE: @_Z7checkmev
-void checkme() {
-// VPTR: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (ptr @bar to
-// VPTR-TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
-  Foo* foo = static_cast<Foo*>(&bar); // down-casting
-// VPTR: ret void
-// VPTR-TYPE: ret void
-  return;
-}
-
 // INT-LABEL: ignore_int
 void ignore_int(int A, int B, unsigned C, unsigned D, long E) {
 // INT: llvm.uadd.with.overflow.i32

>From 4eba983ebfafab7b5ffff00047b5d09bb1fa72c7 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 20:04:41 -0700
Subject: [PATCH 10/12] add clarification about category reordering to docs

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/docs/SanitizerSpecialCaseList.rst | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index ab1f1954d9bfbe..0edd4566190ac9 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -80,11 +80,15 @@ and specifies that the query, if matched, will have its sanitizer
 instrumentation ignored. Conversely, ``sanitize`` causes its queries, if
 matched, to be left out of the ignorelist -- essentially ensuring sanitizer
 instrumentation remains for those types. This is useful for whitelisting
-specific types.
+specific types. If multiple entries for the same type exist, those with the
+``sanitize`` category take precedence.
 
-With this, one may disable instrumentation for all types and specifically allow
-instrumentation for one or many types -- including types created via
-``typedef``.
+With this, one may disable instrumentation for some or all types and
+specifically allow instrumentation for one or many types -- including types
+created via ``typedef``.
+
+The example below shows how one may control the signed truncation sanitizer for
+various types.
 
 .. code-block:: bash
 
@@ -92,6 +96,7 @@ instrumentation for one or many types -- including types created via
   [implicit-signed-integer-truncation]
   type:*=no_sanitize
   type:T=sanitize
+
   $ cat foo.c
   typedef char T;
   typedef char U;

>From 651bc7d2872a8f2b74a7c940f0ebe262e31dfc90 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 21:20:06 -0700
Subject: [PATCH 11/12] use better comparison logic

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/lib/AST/ASTContext.cpp | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f03bacec83ca7c..a0aeb762557ae8 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -843,14 +843,9 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
 /// instrumentation for all types except "size_t".
 bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
                                           const QualType &Ty) const {
-  bool sanitizeType =
-      NoSanitizeL->containsType(Mask, Ty.getAsString(), "sanitize");
-
-  bool noSanitizeType =
-      NoSanitizeL->containsType(Mask, Ty.getAsString(), "no_sanitize") ||
-      NoSanitizeL->containsType(Mask, Ty.getAsString());
-
-  return noSanitizeType && !sanitizeType;
+  return (NoSanitizeL->containsType(Mask, Ty.getAsString()) ||
+          NoSanitizeL->containsType(Mask, Ty.getAsString(), "no_sanitize")) &&
+         !NoSanitizeL->containsType(Mask, Ty.getAsString(), "sanitize");
 }
 
 TargetCXXABI::Kind ASTContext::getCXXABIKind() const {

>From 7156afbb011b8c6e22a0585991ae4d3f6e9ccdc4 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Wed, 30 Oct 2024 22:05:35 -0700
Subject: [PATCH 12/12] use printing policy for type name

Signed-off-by: Justin Stitt <justinstitt at google.com>
---
 clang/lib/AST/ASTContext.cpp | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a0aeb762557ae8..48023389499517 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -843,9 +843,11 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
 /// instrumentation for all types except "size_t".
 bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
                                           const QualType &Ty) const {
-  return (NoSanitizeL->containsType(Mask, Ty.getAsString()) ||
-          NoSanitizeL->containsType(Mask, Ty.getAsString(), "no_sanitize")) &&
-         !NoSanitizeL->containsType(Mask, Ty.getAsString(), "sanitize");
+  std::string TyName = Ty.getUnqualifiedType().getAsString(getPrintingPolicy());
+
+  return (NoSanitizeL->containsType(Mask, TyName) ||
+          NoSanitizeL->containsType(Mask, TyName, "no_sanitize")) &&
+         !NoSanitizeL->containsType(Mask, TyName, "sanitize");
 }
 
 TargetCXXABI::Kind ASTContext::getCXXABIKind() const {



More information about the cfe-commits mailing list