1 //===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This is a utility class for instrumentation passes (like AddressSanitizer
11 // or ThreadSanitizer) to avoid instrumenting some functions or global
12 // variables, or to instrument some functions or global variables in a specific
13 // way, based on a user-supplied list.
15 //===----------------------------------------------------------------------===//
17 #include "llvm/Support/SpecialCaseList.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/Regex.h"
23 #include <system_error>
29 bool SpecialCaseList::Matcher::insert(std::string Regexp
,
31 std::string
&REError
) {
33 REError
= "Supplied regexp was blank";
37 if (Regex::isLiteralERE(Regexp
)) {
38 Strings
[Regexp
] = LineNumber
;
41 Trigrams
.insert(Regexp
);
44 for (size_t pos
= 0; (pos
= Regexp
.find('*', pos
)) != std::string::npos
;
45 pos
+= strlen(".*")) {
46 Regexp
.replace(pos
, strlen("*"), ".*");
49 Regexp
= (Twine("^(") + StringRef(Regexp
) + ")$").str();
51 // Check that the regexp is valid.
52 Regex
CheckRE(Regexp
);
53 if (!CheckRE
.isValid(REError
))
57 std::make_pair(make_unique
<Regex
>(std::move(CheckRE
)), LineNumber
));
61 unsigned SpecialCaseList::Matcher::match(StringRef Query
) const {
62 auto It
= Strings
.find(Query
);
63 if (It
!= Strings
.end())
65 if (Trigrams
.isDefinitelyOut(Query
))
67 for (auto& RegExKV
: RegExes
)
68 if (RegExKV
.first
->match(Query
))
69 return RegExKV
.second
;
73 std::unique_ptr
<SpecialCaseList
>
74 SpecialCaseList::create(const std::vector
<std::string
> &Paths
,
76 std::unique_ptr
<SpecialCaseList
> SCL(new SpecialCaseList());
77 if (SCL
->createInternal(Paths
, Error
))
82 std::unique_ptr
<SpecialCaseList
> SpecialCaseList::create(const MemoryBuffer
*MB
,
84 std::unique_ptr
<SpecialCaseList
> SCL(new SpecialCaseList());
85 if (SCL
->createInternal(MB
, Error
))
90 std::unique_ptr
<SpecialCaseList
>
91 SpecialCaseList::createOrDie(const std::vector
<std::string
> &Paths
) {
93 if (auto SCL
= create(Paths
, Error
))
95 report_fatal_error(Error
);
98 bool SpecialCaseList::createInternal(const std::vector
<std::string
> &Paths
,
100 StringMap
<size_t> Sections
;
101 for (const auto &Path
: Paths
) {
102 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
103 MemoryBuffer::getFile(Path
);
104 if (std::error_code EC
= FileOrErr
.getError()) {
105 Error
= (Twine("can't open file '") + Path
+ "': " + EC
.message()).str();
108 std::string ParseError
;
109 if (!parse(FileOrErr
.get().get(), Sections
, ParseError
)) {
110 Error
= (Twine("error parsing file '") + Path
+ "': " + ParseError
).str();
117 bool SpecialCaseList::createInternal(const MemoryBuffer
*MB
,
118 std::string
&Error
) {
119 StringMap
<size_t> Sections
;
120 if (!parse(MB
, Sections
, Error
))
125 bool SpecialCaseList::parse(const MemoryBuffer
*MB
,
126 StringMap
<size_t> &SectionsMap
,
127 std::string
&Error
) {
128 // Iterate through each line in the blacklist file.
129 SmallVector
<StringRef
, 16> Lines
;
130 MB
->getBuffer().split(Lines
, '\n');
133 StringRef Section
= "*";
135 for (auto I
= Lines
.begin(), E
= Lines
.end(); I
!= E
; ++I
, ++LineNo
) {
137 // Ignore empty lines and lines starting with "#"
138 if (I
->empty() || I
->startswith("#"))
141 // Save section names
142 if (I
->startswith("[")) {
143 if (!I
->endswith("]")) {
144 Error
= (Twine("malformed section header on line ") + Twine(LineNo
) +
149 Section
= I
->slice(1, I
->size() - 1);
152 Regex
CheckRE(Section
);
153 if (!CheckRE
.isValid(REError
)) {
155 (Twine("malformed regex for section ") + Section
+ ": '" + REError
)
163 // Get our prefix and unparsed regexp.
164 std::pair
<StringRef
, StringRef
> SplitLine
= I
->split(":");
165 StringRef Prefix
= SplitLine
.first
;
166 if (SplitLine
.second
.empty()) {
167 // Missing ':' in the line.
168 Error
= (Twine("malformed line ") + Twine(LineNo
) + ": '" +
169 SplitLine
.first
+ "'").str();
173 std::pair
<StringRef
, StringRef
> SplitRegexp
= SplitLine
.second
.split("=");
174 std::string Regexp
= SplitRegexp
.first
;
175 StringRef Category
= SplitRegexp
.second
;
177 // Create this section if it has not been seen before.
178 if (SectionsMap
.find(Section
) == SectionsMap
.end()) {
179 std::unique_ptr
<Matcher
> M
= make_unique
<Matcher
>();
181 if (!M
->insert(Section
, LineNo
, REError
)) {
182 Error
= (Twine("malformed section ") + Section
+ ": '" + REError
).str();
186 SectionsMap
[Section
] = Sections
.size();
187 Sections
.emplace_back(std::move(M
));
190 auto &Entry
= Sections
[SectionsMap
[Section
]].Entries
[Prefix
][Category
];
192 if (!Entry
.insert(std::move(Regexp
), LineNo
, REError
)) {
193 Error
= (Twine("malformed regex in line ") + Twine(LineNo
) + ": '" +
194 SplitLine
.second
+ "': " + REError
).str();
201 SpecialCaseList::~SpecialCaseList() {}
203 bool SpecialCaseList::inSection(StringRef Section
, StringRef Prefix
,
204 StringRef Query
, StringRef Category
) const {
205 return inSectionBlame(Section
, Prefix
, Query
, Category
);
208 unsigned SpecialCaseList::inSectionBlame(StringRef Section
, StringRef Prefix
,
210 StringRef Category
) const {
211 for (auto &SectionIter
: Sections
)
212 if (SectionIter
.SectionMatcher
->match(Section
)) {
214 inSectionBlame(SectionIter
.Entries
, Prefix
, Query
, Category
);
221 unsigned SpecialCaseList::inSectionBlame(const SectionEntries
&Entries
,
222 StringRef Prefix
, StringRef Query
,
223 StringRef Category
) const {
224 SectionEntries::const_iterator I
= Entries
.find(Prefix
);
225 if (I
== Entries
.end()) return 0;
226 StringMap
<Matcher
>::const_iterator II
= I
->second
.find(Category
);
227 if (II
== I
->second
.end()) return 0;
229 return II
->getValue().match(Query
);