Skip to content

Commit 4f1291e

Browse files
authored
[UBSan] Implement src:*=sanitize for UBSan (#140529)
Background: #139128 It is a draft implementation for "src:*=sanitize". It should be applied to all sanitizers. Any srcs assigned to the sanitize category will have their sanitizer instrumentation remained ignored by "src:". For example, ``` src:* src:*/test1.cc=sanitize ``` `test1.cc` will still have the UBSan instrumented. Conflicting entries are resolved by the latest entry, which takes precedence. ``` src:* src:*/mylib/*=sanitize src:*/mylib/test.cc ``` `test.cc` does not have the UBSan check (In this case, `src:*/mylib/test.cc` overrides `src:*/mylib/*=sanitize` for `test.cc`). ``` src:* src:*/mylib/test.cc src:*/mylib/*=sanitize ``` `test1.cc` has the UBSan instrumented (In this case, `src:*/mylib/*=sanitize` overrides `src:*/mylib/test.cc`). Documents update will be in a new PR.
1 parent 1c3cff9 commit 4f1291e

File tree

6 files changed

+82
-17
lines changed

6 files changed

+82
-17
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ Sanitizers
10131013
----------
10141014

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

10171018
Python Binding Changes
10181019
----------------------

clang/docs/SanitizerSpecialCaseList.rst

Lines changed: 21 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+
entries specified within an ignorelist.
6262

6363
.. code-block:: bash
6464
@@ -77,10 +77,9 @@ 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 ``=sanitize`` category
81+
entries enable sanitizer instrumentation, even if it was ignored by entries
82+
before.
8483

8584
With this, one may disable instrumentation for some or all types and
8685
specifically allow instrumentation for one or many types -- including types
@@ -103,6 +102,23 @@ supported sanitizers.
103102
char c = toobig; // also not instrumented
104103
}
105104
105+
If multiple entries match the source, than the latest entry takes the
106+
precedence.
107+
108+
.. code-block:: bash
109+
110+
$ cat ignorelist1.txt
111+
# test.cc will be instrumented.
112+
src:*
113+
src:*/mylib/*=sanitize
114+
src:*/mylib/test.cc
115+
116+
$ cat ignorelist2.txt
117+
# test.cc will not be instrumented.
118+
src:*
119+
src:*/mylib/test.cc
120+
src:*/mylib/*=sanitize
121+
106122
Format
107123
======
108124

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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ 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+
return !SanLine || NoSanLine > SanLine;
4854
}
4955

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

clang/lib/Basic/SanitizerSpecialCaseList.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313
#include "clang/Basic/SanitizerSpecialCaseList.h"
14+
#include "llvm/ADT/STLExtras.h"
1415

1516
using namespace clang;
1617

@@ -56,10 +57,20 @@ void SanitizerSpecialCaseList::createSanitizerSections() {
5657
bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
5758
StringRef Query,
5859
StringRef Category) const {
59-
for (auto &S : SanitizerSections)
60-
if ((S.Mask & Mask) &&
61-
SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category))
62-
return true;
60+
return inSectionBlame(Mask, Prefix, Query, Category);
61+
}
6362

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

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

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
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
// 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
12-
// 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
13-
12+
// 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
13+
// 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
14+
// 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
1415

1516
// Verify ubsan only emits checks for files in the allowlist
1617

@@ -52,6 +53,31 @@ src:*/tes*1.c=sanitize
5253
src:*/te*t1.c
5354
src:*/t*st1.c=sanitize
5455

56+
//--- src.ignorelist.contradict7
57+
[{unsigned-integer-overflow,signed-integer-overflow}]
58+
src:*
59+
src:*/tes*1.c=sanitize
60+
src:*/te*t1.c
61+
src:*/t*st1.c=sanitize
62+
[{unsigned-integer-overflow,signed-integer-overflow}]
63+
src:*
64+
src:*/te*t1.c
65+
src:*/tes*1.c=sanitize
66+
src:*/test1.c
67+
68+
//--- src.ignorelist.contradict8
69+
[{unsigned-integer-overflow,signed-integer-overflow}]
70+
src:*
71+
src:*/te*t1.c
72+
src:*/tes*1.c=sanitize
73+
src:*/test1.c
74+
[{unsigned-integer-overflow,signed-integer-overflow}]
75+
src:*
76+
src:*/tes*1.c=sanitize
77+
src:*/te*t1.c
78+
src:*/t*st1.c=sanitize
79+
80+
5581
//--- test1.c
5682
// CHECK1-LABEL: define dso_local i32 @add
5783
int add(int a, int b) {

0 commit comments

Comments
 (0)