[clang] [llvm] [NFCI] Avoid adding duplicated SpecialCaseList::Sections. (PR #140478)
Qinkun Bao via cfe-commits
cfe-commits at lists.llvm.org
Mon May 19 03:46:04 PDT 2025
https://github.com/qinkunbao updated https://github.com/llvm/llvm-project/pull/140478
>From c51ac31bd7ec778fcbb9faf74d9645384cf67206 Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qinkun at google.com>
Date: Sun, 18 May 2025 20:51:54 +0000
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.6
---
llvm/lib/Support/SpecialCaseList.cpp | 18 +++++++++++------
.../unittests/Support/SpecialCaseListTest.cpp | 20 +++++++++++++++++++
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Support/SpecialCaseList.cpp b/llvm/lib/Support/SpecialCaseList.cpp
index dddf84cbb1ced..926aadb65d493 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -132,18 +132,24 @@ bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
Expected<SpecialCaseList::Section *>
SpecialCaseList::addSection(StringRef SectionStr, unsigned LineNo,
bool UseGlobs) {
- Sections.emplace_back();
- auto &Section = Sections.back();
- Section.SectionStr = SectionStr;
-
- if (auto Err = Section.SectionMatcher->insert(SectionStr, LineNo, UseGlobs)) {
+ auto it =
+ std::find_if(Sections.begin(), Sections.end(), [&](const Section &s) {
+ return s.SectionStr == SectionStr;
+ });
+ if (it == Sections.end()) {
+ Sections.emplace_back();
+ auto &sec = Sections.back();
+ sec.SectionStr = SectionStr;
+ }
+ it = std::prev(Sections.end());
+ if (auto Err = it->SectionMatcher->insert(SectionStr, LineNo, UseGlobs)) {
return createStringError(errc::invalid_argument,
"malformed section at line " + Twine(LineNo) +
": '" + SectionStr +
"': " + toString(std::move(Err)));
}
- return &Section;
+ return &(*it);
}
bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
diff --git a/llvm/unittests/Support/SpecialCaseListTest.cpp b/llvm/unittests/Support/SpecialCaseListTest.cpp
index 4289a5e702155..15dc0222a57c3 100644
--- a/llvm/unittests/Support/SpecialCaseListTest.cpp
+++ b/llvm/unittests/Support/SpecialCaseListTest.cpp
@@ -306,4 +306,24 @@ 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"
+ "fun:foo*\n"
+ "[sect1]\n"
+ "fun:bar*\n"
+ "[sect2]\n"
+ "fun:def\n");
+ EXPECT_TRUE(SCL->inSection("sect1", "fun", "fooz"));
+ EXPECT_TRUE(SCL->inSection("sect1", "fun", "barz"));
+ EXPECT_FALSE(SCL->inSection("sect2", "fun", "fooz"));
+
+ EXPECT_TRUE(SCL->inSection("sect2", "fun", "def"));
+ EXPECT_FALSE(SCL->inSection("sect1", "fun", "def"));
+
+ EXPECT_EQ(2u, SCL->inSectionBlame("sect1", "fun", "fooz"));
+ EXPECT_EQ(4u, SCL->inSectionBlame("sect1", "fun", "barz"));
+ EXPECT_EQ(6u, SCL->inSectionBlame("sect2", "fun", "def"));
+}
+
}
>From 330e276fd300476df4b4ad1bd5e5c71a80f4e585 Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qinkun at google.com>
Date: Mon, 19 May 2025 10:45:23 +0000
Subject: [PATCH 2/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.6
[skip ci]
---
.../clang/Basic/SanitizerSpecialCaseList.h | 7 +++-
clang/lib/Basic/NoSanitizeList.cpp | 7 ++++
clang/lib/Basic/SanitizerSpecialCaseList.cpp | 16 ++++++++
.../ubsan-src-ignorelist-category.test | 37 +++++++++++++++++++
4 files changed, 66 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGen/ubsan-src-ignorelist-category.test
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..811480f914ec5 100644
--- a/clang/lib/Basic/NoSanitizeList.cpp
+++ b/clang/lib/Basic/NoSanitizeList.cpp
@@ -44,6 +44,13 @@ bool NoSanitizeList::containsFunction(SanitizerMask Mask,
bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
StringRef Category) const {
+ unsigned nosanline = SSCL->inSectionBlame(Mask, "src", FileName, Category);
+ 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 (nosanline > 0 && sanline > 0) {
+ return nosanline > sanline;
+ }
return SSCL->inSection(Mask, "src", FileName, Category);
}
diff --git a/clang/lib/Basic/SanitizerSpecialCaseList.cpp b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
index 2dbf04c6ede97..7da36f3801453 100644
--- a/clang/lib/Basic/SanitizerSpecialCaseList.cpp
+++ b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -63,3 +63,19 @@ bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
return false;
}
+
+unsigned SanitizerSpecialCaseList::inSectionBlame(SanitizerMask Mask,
+ StringRef Prefix,
+ StringRef Query,
+ StringRef Category) const {
+ for (auto &S : SanitizerSections) {
+ if (S.Mask & Mask) {
+ unsigned lineNum =
+ SpecialCaseList::inSectionBlame(S.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
new file mode 100644
index 0000000000000..e0efd65df8652
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-src-ignorelist-category.test
@@ -0,0 +1,37 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// 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-prefix=CHECK-ALLOWLIST
+// 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-prefix=CHECK-IGNORELIST
+// 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-prefix=CHECK-ALLOWLISTOVERIDE1
+// 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-prefix=CHECK-ALLOWLISTOVERIDE2
+
+
+// Verify ubsan only emits checks for files in the allowlist
+
+//--- src.ignorelist
+src:*
+src:*/test1.c=sanitize
+
+//--- src.ignorelist.contradict1
+src:*
+src:*/test1.c=sanitize
+src:*/test1.c
+
+//--- src.ignorelist.contradict2
+src:*
+src:*/test1.c
+src:*/test1.c=sanitize
+
+//--- test1.c
+int add1(int a, int b) {
+// CHECK-ALLOWLIST: llvm.sadd.with.overflow.i32
+// CHECK-ALLOWLISTOVERIDE1-NOT: llvm.sadd.with.overflow.i32
+// CHECK-ALLOWLISTOVERIDE2: llvm.sadd.with.overflow.i32
+ return a+b;
+}
+
+//--- test2.c
+int add2(int a, int b) {
+// CHECK-IGNORELIST-NOT: llvm.sadd.with.overflow.i32
+ return a+b;
+}
>From e6ad7e8d7efca449d5238a8147449f80bb61d7ad Mon Sep 17 00:00:00 2001
From: Qinkun Bao <qinkun at google.com>
Date: Mon, 19 May 2025 10:45:51 +0000
Subject: [PATCH 3/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.6
[skip ci]
---
.../clang/Basic/SanitizerSpecialCaseList.h | 7 +++-
clang/lib/Basic/NoSanitizeList.cpp | 7 ++++
clang/lib/Basic/SanitizerSpecialCaseList.cpp | 16 ++++++++
.../ubsan-src-ignorelist-category.test | 37 +++++++++++++++++++
4 files changed, 66 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGen/ubsan-src-ignorelist-category.test
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..811480f914ec5 100644
--- a/clang/lib/Basic/NoSanitizeList.cpp
+++ b/clang/lib/Basic/NoSanitizeList.cpp
@@ -44,6 +44,13 @@ bool NoSanitizeList::containsFunction(SanitizerMask Mask,
bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
StringRef Category) const {
+ unsigned nosanline = SSCL->inSectionBlame(Mask, "src", FileName, Category);
+ 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 (nosanline > 0 && sanline > 0) {
+ return nosanline > sanline;
+ }
return SSCL->inSection(Mask, "src", FileName, Category);
}
diff --git a/clang/lib/Basic/SanitizerSpecialCaseList.cpp b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
index 2dbf04c6ede97..7da36f3801453 100644
--- a/clang/lib/Basic/SanitizerSpecialCaseList.cpp
+++ b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -63,3 +63,19 @@ bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
return false;
}
+
+unsigned SanitizerSpecialCaseList::inSectionBlame(SanitizerMask Mask,
+ StringRef Prefix,
+ StringRef Query,
+ StringRef Category) const {
+ for (auto &S : SanitizerSections) {
+ if (S.Mask & Mask) {
+ unsigned lineNum =
+ SpecialCaseList::inSectionBlame(S.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
new file mode 100644
index 0000000000000..e0efd65df8652
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-src-ignorelist-category.test
@@ -0,0 +1,37 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// 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-prefix=CHECK-ALLOWLIST
+// 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-prefix=CHECK-IGNORELIST
+// 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-prefix=CHECK-ALLOWLISTOVERIDE1
+// 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-prefix=CHECK-ALLOWLISTOVERIDE2
+
+
+// Verify ubsan only emits checks for files in the allowlist
+
+//--- src.ignorelist
+src:*
+src:*/test1.c=sanitize
+
+//--- src.ignorelist.contradict1
+src:*
+src:*/test1.c=sanitize
+src:*/test1.c
+
+//--- src.ignorelist.contradict2
+src:*
+src:*/test1.c
+src:*/test1.c=sanitize
+
+//--- test1.c
+int add1(int a, int b) {
+// CHECK-ALLOWLIST: llvm.sadd.with.overflow.i32
+// CHECK-ALLOWLISTOVERIDE1-NOT: llvm.sadd.with.overflow.i32
+// CHECK-ALLOWLISTOVERIDE2: llvm.sadd.with.overflow.i32
+ return a+b;
+}
+
+//--- test2.c
+int add2(int a, int b) {
+// CHECK-IGNORELIST-NOT: llvm.sadd.with.overflow.i32
+ return a+b;
+}
More information about the cfe-commits
mailing list