https://github.com/vitalybuka updated 
https://github.com/llvm/llvm-project/pull/141540

>From e7540c31c69df827d646e88b271a355c587bd9da Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qin...@google.com>
Date: Tue, 27 May 2025 02:36:29 +0000
Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
 =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6

[skip ci]
---
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/docs/SanitizerSpecialCaseList.rst       | 26 +++++++++++---
 .../clang/Basic/SanitizerSpecialCaseList.h    |  7 +++-
 clang/lib/Basic/NoSanitizeList.cpp            | 10 +++++-
 clang/lib/Basic/SanitizerSpecialCaseList.cpp  | 21 ++++++++---
 .../ubsan-src-ignorelist-category.test        | 36 ++++++++++++++++---
 llvm/lib/Support/SpecialCaseList.cpp          | 18 +++++-----
 .../unittests/Support/SpecialCaseListTest.cpp | 23 ++++++++++++
 8 files changed, 116 insertions(+), 26 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b93fa33acc2a0..80a5b7072677d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1009,6 +1009,7 @@ Sanitizers
 ----------
 
 - ``-fsanitize=vptr`` is no longer a part of ``-fsanitize=undefined``.
+- Sanitizer ignorelists now support the syntax ``src:*=sanitize``.
 
 Python Binding Changes
 ----------------------
diff --git a/clang/docs/SanitizerSpecialCaseList.rst 
b/clang/docs/SanitizerSpecialCaseList.rst
index 5c88c2976e861..692af8df0359b 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -58,7 +58,7 @@ Usage with UndefinedBehaviorSanitizer
 ability to adjust instrumentation based on type.
 
 By default, supported sanitizers will have their instrumentation disabled for
-types specified within an ignorelist.
+entries specified within an ignorelist.
 
 .. code-block:: bash
 
@@ -77,10 +77,9 @@ 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 ``=sanitize`` category is also supported. Any types assigned to the
-``sanitize`` category will have their sanitizer instrumentation remain. If the
-same type appears within or across ignorelists with different categories the
-``sanitize`` category takes precedence -- regardless of order.
+The ``=sanitize`` category is also supported. Any ``=sanitize`` category
+entries enable sanitizer instrumentation, even if it was ignored by entries
+before.
 
 With this, one may disable instrumentation for some or all types and
 specifically allow instrumentation for one or many types -- including types
@@ -103,6 +102,23 @@ supported sanitizers.
     char c = toobig; // also not instrumented
   }
 
+If multiple entries match the source, than the latest entry takes the
+precedence.
+
+.. code-block:: bash
+
+  $ cat ignorelist1.txt
+  # test.cc will be instrumented.
+  src:*
+  src:*/mylib/*=sanitize
+  src:*/mylib/test.cc
+
+  $ cat ignorelist2.txt
+  # test.cc will not be instrumented.
+  src:*
+  src:*/mylib/test.cc
+  src:*/mylib/*=sanitize
+
 Format
 ======
 
diff --git a/clang/include/clang/Basic/SanitizerSpecialCaseList.h 
b/clang/include/clang/Basic/SanitizerSpecialCaseList.h
index d024b7dfc2e85..25d518e7128cf 100644
--- a/clang/include/clang/Basic/SanitizerSpecialCaseList.h
+++ b/clang/include/clang/Basic/SanitizerSpecialCaseList.h
@@ -43,13 +43,18 @@ class SanitizerSpecialCaseList : public 
llvm::SpecialCaseList {
   bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,
                  StringRef Category = StringRef()) const;
 
+  // Query ignorelisted entries if any bit in Mask matches the entry's section.
+  // Return 0 if not found. If found, return the line number (starts with 1).
+  unsigned inSectionBlame(SanitizerMask Mask, StringRef Prefix, StringRef 
Query,
+                          StringRef Category = StringRef()) const;
+
 protected:
   // Initialize SanitizerSections.
   void createSanitizerSections();
 
   struct SanitizerSection {
     SanitizerSection(SanitizerMask SM, SectionEntries &E)
-        : Mask(SM), Entries(E){};
+        : Mask(SM), Entries(E) {};
 
     SanitizerMask Mask;
     SectionEntries &Entries;
diff --git a/clang/lib/Basic/NoSanitizeList.cpp 
b/clang/lib/Basic/NoSanitizeList.cpp
index e7e63c1f419e6..4feef5c6ea052 100644
--- a/clang/lib/Basic/NoSanitizeList.cpp
+++ b/clang/lib/Basic/NoSanitizeList.cpp
@@ -44,7 +44,15 @@ bool NoSanitizeList::containsFunction(SanitizerMask Mask,
 
 bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
                                   StringRef Category) const {
-  return SSCL->inSection(Mask, "src", FileName, Category);
+  unsigned NoSanLine = SSCL->inSectionBlame(Mask, "src", FileName, Category);
+  if (NoSanLine == 0)
+    return false;
+  unsigned SanLine = SSCL->inSectionBlame(Mask, "src", FileName, "sanitize");
+  // If we have two cases such as `src:a.cpp=sanitize` and `src:a.cpp`, the
+  // current entry override the previous entry.
+  if (SanLine > 0)
+    return NoSanLine > SanLine;
+  return true;
 }
 
 bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,
diff --git a/clang/lib/Basic/SanitizerSpecialCaseList.cpp 
b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
index 2dbf04c6ede97..4508d705eb43a 100644
--- a/clang/lib/Basic/SanitizerSpecialCaseList.cpp
+++ b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -56,10 +56,21 @@ void SanitizerSpecialCaseList::createSanitizerSections() {
 bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
                                          StringRef Query,
                                          StringRef Category) const {
-  for (auto &S : SanitizerSections)
-    if ((S.Mask & Mask) &&
-        SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category))
-      return true;
+  return inSectionBlame(Mask, Prefix, Query, Category);
+}
 
-  return false;
+unsigned SanitizerSpecialCaseList::inSectionBlame(SanitizerMask Mask,
+                                                  StringRef Prefix,
+                                                  StringRef Query,
+                                                  StringRef Category) const {
+  for (auto it = SanitizerSections.crbegin(); it != SanitizerSections.crend();
+       ++it) {
+    if (it->Mask & Mask) {
+      unsigned lineNum =
+          SpecialCaseList::inSectionBlame(it->Entries, Prefix, Query, 
Category);
+      if (lineNum > 0)
+        return lineNum;
+    }
+  }
+  return 0;
 }
diff --git a/clang/test/CodeGen/ubsan-src-ignorelist-category.test 
b/clang/test/CodeGen/ubsan-src-ignorelist-category.test
index 2f196fb126fe7..55967ec77c836 100644
--- a/clang/test/CodeGen/ubsan-src-ignorelist-category.test
+++ b/clang/test/CodeGen/ubsan-src-ignorelist-category.test
@@ -3,14 +3,15 @@
 
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist -emit-llvm %t/test2.c -o -             
| FileCheck %s --check-prefixes=CHECK2
 
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist -emit-llvm %t/test1.c -o -             
| FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist -emit-llvm %t/test1.c -o -             
| FileCheck %s --check-prefixes=CHECK1,SANITIZE
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict1 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict2 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict2 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,SANITIZE
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict3 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict4 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict4 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,SANITIZE
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict5 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict6 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
-
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict6 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,SANITIZE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict7 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,IGNORE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=%t/src.ignorelist.contradict8 -emit-llvm %t/test1.c -o - 
| FileCheck %s --check-prefixes=CHECK1,SANITIZE
 
 // Verify ubsan only emits checks for files in the allowlist
 
@@ -52,6 +53,31 @@ src:*/tes*1.c=sanitize
 src:*/te*t1.c
 src:*/t*st1.c=sanitize
 
+//--- src.ignorelist.contradict7
+[{unsigned-integer-overflow,signed-integer-overflow}]
+src:*
+src:*/tes*1.c=sanitize
+src:*/te*t1.c
+src:*/t*st1.c=sanitize
+[{unsigned-integer-overflow,signed-integer-overflow}]
+src:*
+src:*/te*t1.c
+src:*/tes*1.c=sanitize
+src:*/test1.c
+
+//--- src.ignorelist.contradict8
+[{unsigned-integer-overflow,signed-integer-overflow}]
+src:*
+src:*/te*t1.c
+src:*/tes*1.c=sanitize
+src:*/test1.c
+[{unsigned-integer-overflow,signed-integer-overflow}]
+src:*
+src:*/tes*1.c=sanitize
+src:*/te*t1.c
+src:*/t*st1.c=sanitize
+
+
 //--- test1.c
 // CHECK1-LABEL: define dso_local i32 @add
 int add(int a, int b) {
diff --git a/llvm/lib/Support/SpecialCaseList.cpp 
b/llvm/lib/Support/SpecialCaseList.cpp
index 47ff3e24706a4..56327b56282c2 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -66,12 +66,12 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, 
unsigned LineNumber,
 }
 
 unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
-  for (const auto &Glob : Globs)
-    if (Glob->Pattern.match(Query))
-      return Glob->LineNo;
-  for (const auto &[Regex, LineNumber] : RegExes)
-    if (Regex->match(Query))
-      return LineNumber;
+  for (auto it = Globs.crbegin(); it != Globs.crend(); ++it)
+    if ((*it)->Pattern.match(Query))
+      return (*it)->LineNo;
+  for (auto it = RegExes.crbegin(); it != RegExes.crend(); ++it)
+    if (it->first->match(Query))
+      return it->second;
   return 0;
 }
 
@@ -213,9 +213,9 @@ bool SpecialCaseList::inSection(StringRef Section, 
StringRef Prefix,
 unsigned SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
                                          StringRef Query,
                                          StringRef Category) const {
-  for (const auto &S : Sections) {
-    if (S.SectionMatcher->match(Section)) {
-      unsigned Blame = inSectionBlame(S.Entries, Prefix, Query, Category);
+  for (auto it = Sections.crbegin(); it != Sections.crend(); ++it) {
+    if (it->SectionMatcher->match(Section)) {
+      unsigned Blame = inSectionBlame(it->Entries, Prefix, Query, Category);
       if (Blame)
         return Blame;
     }
diff --git a/llvm/unittests/Support/SpecialCaseListTest.cpp 
b/llvm/unittests/Support/SpecialCaseListTest.cpp
index 4289a5e702155..ce58328f396b6 100644
--- a/llvm/unittests/Support/SpecialCaseListTest.cpp
+++ b/llvm/unittests/Support/SpecialCaseListTest.cpp
@@ -306,4 +306,27 @@ TEST_F(SpecialCaseListTest, Version2) {
   EXPECT_TRUE(SCL->inSection("sect2", "fun", "bar"));
   EXPECT_FALSE(SCL->inSection("sect3", "fun", "bar"));
 }
+
+TEST_F(SpecialCaseListTest, Version3) {
+  std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("[sect1]\n"
+                                                             "src:foo*\n"
+                                                             "[sect1]\n"
+                                                             "src:bar*\n"
+                                                             "src:def\n"
+                                                             "[sect2]\n"
+                                                             "src:def\n"
+                                                             "src:de*\n");
+  EXPECT_TRUE(SCL->inSection("sect1", "src", "fooz"));
+  EXPECT_TRUE(SCL->inSection("sect1", "src", "barz"));
+  EXPECT_FALSE(SCL->inSection("sect2", "src", "fooz"));
+
+  EXPECT_TRUE(SCL->inSection("sect2", "src", "def"));
+  EXPECT_TRUE(SCL->inSection("sect1", "src", "def"));
+
+  EXPECT_EQ(2u, SCL->inSectionBlame("sect1", "src", "fooz"));
+  EXPECT_EQ(4u, SCL->inSectionBlame("sect1", "src", "barz"));
+  EXPECT_EQ(5u, SCL->inSectionBlame("sect1", "src", "def"));
+  EXPECT_EQ(8u, SCL->inSectionBlame("sect2", "src", "def"));
+  EXPECT_EQ(8u, SCL->inSectionBlame("sect2", "src", "dez"));
+}
 }

>From d5508cc217f413b3bbb7a301b2110cfc0c2c6cbc Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qin...@google.com>
Date: Tue, 27 May 2025 03:24:26 +0000
Subject: [PATCH 2/4] Format SpecialCaseList.h

Created using spr 1.3.6
---
 llvm/include/llvm/Support/SpecialCaseList.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Support/SpecialCaseList.h 
b/llvm/include/llvm/Support/SpecialCaseList.h
index bce337f553a93..d54b242a9c501 100644
--- a/llvm/include/llvm/Support/SpecialCaseList.h
+++ b/llvm/include/llvm/Support/SpecialCaseList.h
@@ -17,8 +17,8 @@
 #include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/Regex.h"
 #include <memory>
-#include <utility>
 #include <string>
+#include <utility>
 #include <vector>
 
 namespace llvm {

>From b094fc2f5e3fe0d9b65f86a3f6eda04a6ab41e47 Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qin...@google.com>
Date: Tue, 27 May 2025 14:01:19 +0000
Subject: [PATCH 3/4] Remove irelevant format changes

Created using spr 1.3.6
---
 llvm/unittests/Support/SpecialCaseListTest.cpp | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/llvm/unittests/Support/SpecialCaseListTest.cpp 
b/llvm/unittests/Support/SpecialCaseListTest.cpp
index da4c557e740e6..0fe6a427c0562 100644
--- a/llvm/unittests/Support/SpecialCaseListTest.cpp
+++ b/llvm/unittests/Support/SpecialCaseListTest.cpp
@@ -218,9 +218,8 @@ TEST_F(SpecialCaseListTest, NoTrigramsInARule) {
 }
 
 TEST_F(SpecialCaseListTest, RepetitiveRule) {
-  std::unique_ptr<SpecialCaseList> SCL =
-      makeSpecialCaseList("fun:*bar*bar*bar*bar*\n"
-                          "fun:bar*\n");
+  std::unique_ptr<SpecialCaseList> SCL = 
makeSpecialCaseList("fun:*bar*bar*bar*bar*\n"
+                                                             "fun:bar*\n");
   EXPECT_TRUE(SCL->inSection("", "fun", "bara"));
   EXPECT_FALSE(SCL->inSection("", "fun", "abara"));
   EXPECT_TRUE(SCL->inSection("", "fun", "barbarbarbar"));
@@ -229,8 +228,7 @@ TEST_F(SpecialCaseListTest, RepetitiveRule) {
 }
 
 TEST_F(SpecialCaseListTest, SpecialSymbolRule) {
-  std::unique_ptr<SpecialCaseList> SCL =
-      makeSpecialCaseList("src:*c\\+\\+abi*\n");
+  std::unique_ptr<SpecialCaseList> SCL = 
makeSpecialCaseList("src:*c\\+\\+abi*\n");
   EXPECT_TRUE(SCL->inSection("", "src", "c++abi"));
   EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi"));
 }
@@ -246,9 +244,8 @@ TEST_F(SpecialCaseListTest, PopularTrigram) {
 }
 
 TEST_F(SpecialCaseListTest, EscapedSymbols) {
-  std::unique_ptr<SpecialCaseList> SCL =
-      makeSpecialCaseList("src:*c\\+\\+abi*\n"
-                          "src:*hello\\\\world*\n");
+  std::unique_ptr<SpecialCaseList> SCL = 
makeSpecialCaseList("src:*c\\+\\+abi*\n"
+                                                             
"src:*hello\\\\world*\n");
   EXPECT_TRUE(SCL->inSection("", "src", "dir/c++abi"));
   EXPECT_FALSE(SCL->inSection("", "src", "dir/c\\+\\+abi"));
   EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi"));

>From a898b892432d1e7b27b671dc5cae3d9b17de1c65 Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qin...@google.com>
Date: Tue, 27 May 2025 20:11:16 -0700
Subject: [PATCH 4/4] NotFound

Created using spr 1.3.6
---
 llvm/include/llvm/Support/SpecialCaseList.h | 1 +
 llvm/lib/Support/SpecialCaseList.cpp        | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Support/SpecialCaseList.h 
b/llvm/include/llvm/Support/SpecialCaseList.h
index b21c6a4931eb6..5d6f3a374bb6d 100644
--- a/llvm/include/llvm/Support/SpecialCaseList.h
+++ b/llvm/include/llvm/Support/SpecialCaseList.h
@@ -70,6 +70,7 @@ class FileSystem;
 /// ---
 class SpecialCaseList {
 public:
+  constexpr static std::pair<unsigned, unsigned> NotFound = {0, 0};
   /// Parses the special case list entries from files. On failure, returns
   /// 0 and writes an error message to string.
   LLVM_ABI static std::unique_ptr<SpecialCaseList>
diff --git a/llvm/lib/Support/SpecialCaseList.cpp 
b/llvm/lib/Support/SpecialCaseList.cpp
index 00f3409e37f13..8d4e043bc1c9f 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -224,7 +224,7 @@ SpecialCaseList::inSectionBlame(StringRef Section, 
StringRef Prefix,
         return {S.FileIdx, Blame};
     }
   }
-  return {0, 0};
+  return NotFound;
 }
 
 unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to