Skip to content

Commit 21352cb

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.6
2 parents 5db4aea + 6516ba4 commit 21352cb

File tree

9 files changed

+94
-21
lines changed

9 files changed

+94
-21
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ Sanitizers
960960
----------
961961

962962
- ``-fsanitize=vptr`` is no longer a part of ``-fsanitize=undefined``.
963+
- Sanitizer ignorelists now support the syntax ``src:*=sanitize``.
963964

964965
Python Binding Changes
965966
----------------------

clang/docs/SanitizerSpecialCaseList.rst

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Usage with UndefinedBehaviorSanitizer
5858
ability to adjust instrumentation based on type.
5959

6060
By default, supported sanitizers will have their instrumentation disabled for
61-
types specified within an ignorelist.
61+
entris specified within an ignorelist.
6262

6363
.. code-block:: bash
6464
@@ -77,10 +77,8 @@ For example, supplying the above ``ignorelist.txt`` to
7777
``-fsanitize-ignorelist=ignorelist.txt`` disables overflow sanitizer
7878
instrumentation for arithmetic operations containing values of type ``int``.
7979

80-
The ``=sanitize`` category is also supported. Any types assigned to the
81-
``sanitize`` category will have their sanitizer instrumentation remain. If the
82-
same type appears within or across ignorelists with different categories the
83-
``sanitize`` category takes precedence -- regardless of order.
80+
The ``=sanitize`` category is also supported. Any entries assigned to the
81+
``sanitize`` category will have their sanitizer instrumentation remain.
8482

8583
With this, one may disable instrumentation for some or all types and
8684
specifically allow instrumentation for one or many types -- including types
@@ -103,6 +101,22 @@ supported sanitizers.
103101
char c = toobig; // also not instrumented
104102
}
105103
104+
Conflicting entries are resolved by the latest entry, which takes precedence.
105+
106+
.. code-block:: bash
107+
108+
$ cat ignorelist1.txt
109+
# test.cc will be instrumented.
110+
src:*
111+
src:*/mylib/*=sanitize
112+
src:*/mylib/test.cc
113+
114+
$ cat ignorelist2.txt
115+
# test.cc will not be instrumented.
116+
src:*
117+
src:*/mylib/test.cc
118+
src:*/mylib/*=sanitize
119+
106120
Format
107121
======
108122

clang/include/clang/Basic/SanitizerSpecialCaseList.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,18 @@ class SanitizerSpecialCaseList : public llvm::SpecialCaseList {
4343
bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,
4444
StringRef Category = StringRef()) const;
4545

46+
// Query ignorelisted entries if any bit in Mask matches the entry's section.
47+
// Return 0 if not found. If found, return the line number (starts with 1).
48+
unsigned inSectionBlame(SanitizerMask Mask, StringRef Prefix, StringRef Query,
49+
StringRef Category = StringRef()) const;
50+
4651
protected:
4752
// Initialize SanitizerSections.
4853
void createSanitizerSections();
4954

5055
struct SanitizerSection {
5156
SanitizerSection(SanitizerMask SM, SectionEntries &E)
52-
: Mask(SM), Entries(E){};
57+
: Mask(SM), Entries(E) {};
5358

5459
SanitizerMask Mask;
5560
SectionEntries &Entries;

clang/lib/Basic/NoSanitizeList.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,15 @@ bool NoSanitizeList::containsFunction(SanitizerMask Mask,
4444

4545
bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
4646
StringRef Category) const {
47-
return SSCL->inSection(Mask, "src", FileName, Category);
47+
unsigned NoSanLine = SSCL->inSectionBlame(Mask, "src", FileName, Category);
48+
if (NoSanLine == 0)
49+
return false;
50+
unsigned SanLine = SSCL->inSectionBlame(Mask, "src", FileName, "sanitize");
51+
// If we have two cases such as `src:a.cpp=sanitize` and `src:a.cpp`, the
52+
// current entry override the previous entry.
53+
if (SanLine > 0)
54+
return NoSanLine > SanLine;
55+
return true;
4856
}
4957

5058
bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,

clang/lib/Basic/SanitizerSpecialCaseList.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,20 @@ void SanitizerSpecialCaseList::createSanitizerSections() {
5656
bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
5757
StringRef Query,
5858
StringRef Category) const {
59-
for (auto &S : SanitizerSections)
60-
if ((S.Mask & Mask) &&
61-
SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category))
62-
return true;
59+
return inSectionBlame(Mask, Prefix, Query, Category) > 0;
60+
}
6361

64-
return false;
62+
unsigned SanitizerSpecialCaseList::inSectionBlame(SanitizerMask Mask,
63+
StringRef Prefix,
64+
StringRef Query,
65+
StringRef Category) const {
66+
for (auto &S : SanitizerSections) {
67+
if (S.Mask & Mask) {
68+
unsigned lineNum =
69+
SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category);
70+
if (lineNum > 0)
71+
return lineNum;
72+
}
73+
}
74+
return 0;
6575
}

clang/test/CodeGen/ubsan-src-ignorelist-category.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
// 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
55

6-
// 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
6+
// 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
77
// 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
8-
// 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
8+
// 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
99
// 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
10-
// 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
10+
// 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
1111

1212

1313
// Verify ubsan only emits checks for files in the allowlist

llvm/include/llvm/Support/SpecialCaseList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ class SpecialCaseList {
138138
std::unique_ptr<Matcher> SectionMatcher;
139139
SectionEntries Entries;
140140
std::string SectionStr;
141+
unsigned LineNo;
141142
};
142143

143144
std::vector<Section> Sections;

llvm/lib/Support/SpecialCaseList.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, unsigned LineNumber,
6363
.moveInto(Pair.first))
6464
return Err;
6565
Pair.second = LineNumber;
66+
} else {
67+
// We should update the new line number if an entry with the same pattern
68+
// repeats.
69+
auto &Pair = It->getValue();
70+
Pair.second = LineNumber;
6671
}
6772
return Error::success();
6873
}
@@ -132,18 +137,25 @@ bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
132137
Expected<SpecialCaseList::Section *>
133138
SpecialCaseList::addSection(StringRef SectionStr, unsigned LineNo,
134139
bool UseGlobs) {
135-
Sections.emplace_back();
136-
auto &Section = Sections.back();
137-
Section.SectionStr = SectionStr;
138-
139-
if (auto Err = Section.SectionMatcher->insert(SectionStr, LineNo, UseGlobs)) {
140+
auto it =
141+
std::find_if(Sections.begin(), Sections.end(), [&](const Section &s) {
142+
return s.SectionStr == SectionStr && s.LineNo == LineNo;
143+
});
144+
if (it == Sections.end()) {
145+
Sections.emplace_back();
146+
auto &sec = Sections.back();
147+
sec.SectionStr = SectionStr;
148+
sec.LineNo = LineNo;
149+
it = std::prev(Sections.end());
150+
}
151+
if (auto Err = it->SectionMatcher->insert(SectionStr, LineNo, UseGlobs)) {
140152
return createStringError(errc::invalid_argument,
141153
"malformed section at line " + Twine(LineNo) +
142154
": '" + SectionStr +
143155
"': " + toString(std::move(Err)));
144156
}
145157

146-
return &Section;
158+
return &(*it);
147159
}
148160

149161
bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {

llvm/unittests/Support/SpecialCaseListTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,4 +306,26 @@ TEST_F(SpecialCaseListTest, Version2) {
306306
EXPECT_TRUE(SCL->inSection("sect2", "fun", "bar"));
307307
EXPECT_FALSE(SCL->inSection("sect3", "fun", "bar"));
308308
}
309+
310+
TEST_F(SpecialCaseListTest, Version3) {
311+
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("[sect1]\n"
312+
"src:foo*\n"
313+
"[sect1]\n"
314+
"src:bar*\n"
315+
"src:def\n"
316+
"[sect2]\n"
317+
"src:def\n"
318+
"src:def\n");
319+
EXPECT_TRUE(SCL->inSection("sect1", "src", "fooz"));
320+
EXPECT_TRUE(SCL->inSection("sect1", "src", "barz"));
321+
EXPECT_FALSE(SCL->inSection("sect2", "src", "fooz"));
322+
323+
EXPECT_TRUE(SCL->inSection("sect2", "src", "def"));
324+
EXPECT_TRUE(SCL->inSection("sect1", "src", "def"));
325+
326+
EXPECT_EQ(2u, SCL->inSectionBlame("sect1", "src", "fooz"));
327+
EXPECT_EQ(4u, SCL->inSectionBlame("sect1", "src", "barz"));
328+
EXPECT_EQ(5u, SCL->inSectionBlame("sect1", "src", "def"));
329+
EXPECT_EQ(8u, SCL->inSectionBlame("sect2", "src", "def"));
330+
}
309331
}

0 commit comments

Comments
 (0)