LLVM  3.7.0
SpecialCaseList.cpp
Go to the documentation of this file.
1 //===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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.
14 //
15 //===----------------------------------------------------------------------===//
16 
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringSet.h"
22 #include "llvm/Support/Regex.h"
23 #include <string>
24 #include <system_error>
25 #include <utility>
26 
27 namespace llvm {
28 
29 /// Represents a set of regular expressions. Regular expressions which are
30 /// "literal" (i.e. no regex metacharacters) are stored in Strings, while all
31 /// others are represented as a single pipe-separated regex in RegEx. The
32 /// reason for doing so is efficiency; StringSet is much faster at matching
33 /// literal strings than Regex.
35  Entry() {}
37  : Strings(std::move(Other.Strings)), RegEx(std::move(Other.RegEx)) {}
38 
40  std::unique_ptr<Regex> RegEx;
41 
42  bool match(StringRef Query) const {
43  return Strings.count(Query) || (RegEx && RegEx->match(Query));
44  }
45 };
46 
47 SpecialCaseList::SpecialCaseList() : Entries(), Regexps(), IsCompiled(false) {}
48 
49 std::unique_ptr<SpecialCaseList>
50 SpecialCaseList::create(const std::vector<std::string> &Paths,
51  std::string &Error) {
52  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
53  for (auto Path : Paths) {
56  if (std::error_code EC = FileOrErr.getError()) {
57  Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
58  return nullptr;
59  }
60  std::string ParseError;
61  if (!SCL->parse(FileOrErr.get().get(), ParseError)) {
62  Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
63  return nullptr;
64  }
65  }
66  SCL->compile();
67  return SCL;
68 }
69 
70 std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
71  std::string &Error) {
72  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
73  if (!SCL->parse(MB, Error))
74  return nullptr;
75  SCL->compile();
76  return SCL;
77 }
78 
79 std::unique_ptr<SpecialCaseList>
80 SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
81  std::string Error;
82  if (auto SCL = create(Paths, Error))
83  return SCL;
84  report_fatal_error(Error);
85 }
86 
87 bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
88  // Iterate through each line in the blacklist file.
90  SplitString(MB->getBuffer(), Lines, "\n\r");
91  int LineNo = 1;
92  for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
93  // Ignore empty lines and lines starting with "#"
94  if (I->empty() || I->startswith("#"))
95  continue;
96  // Get our prefix and unparsed regexp.
97  std::pair<StringRef, StringRef> SplitLine = I->split(":");
98  StringRef Prefix = SplitLine.first;
99  if (SplitLine.second.empty()) {
100  // Missing ':' in the line.
101  Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
102  SplitLine.first + "'").str();
103  return false;
104  }
105 
106  std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
107  std::string Regexp = SplitRegexp.first;
108  StringRef Category = SplitRegexp.second;
109 
110  // See if we can store Regexp in Strings.
111  if (Regex::isLiteralERE(Regexp)) {
112  Entries[Prefix][Category].Strings.insert(Regexp);
113  continue;
114  }
115 
116  // Replace * with .*
117  for (size_t pos = 0; (pos = Regexp.find("*", pos)) != std::string::npos;
118  pos += strlen(".*")) {
119  Regexp.replace(pos, strlen("*"), ".*");
120  }
121 
122  // Check that the regexp is valid.
123  Regex CheckRE(Regexp);
124  std::string REError;
125  if (!CheckRE.isValid(REError)) {
126  Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
127  SplitLine.second + "': " + REError).str();
128  return false;
129  }
130 
131  // Add this regexp into the proper group by its prefix.
132  if (!Regexps[Prefix][Category].empty())
133  Regexps[Prefix][Category] += "|";
134  Regexps[Prefix][Category] += "^" + Regexp + "$";
135  }
136  return true;
137 }
138 
139 void SpecialCaseList::compile() {
140  assert(!IsCompiled && "compile() should only be called once");
141  // Iterate through each of the prefixes, and create Regexs for them.
142  for (StringMap<StringMap<std::string>>::const_iterator I = Regexps.begin(),
143  E = Regexps.end();
144  I != E; ++I) {
145  for (StringMap<std::string>::const_iterator II = I->second.begin(),
146  IE = I->second.end();
147  II != IE; ++II) {
148  Entries[I->getKey()][II->getKey()].RegEx.reset(new Regex(II->getValue()));
149  }
150  }
151  Regexps.clear();
152  IsCompiled = true;
153 }
154 
156 
158  StringRef Category) const {
159  assert(IsCompiled && "SpecialCaseList::compile() was not called!");
160  StringMap<StringMap<Entry> >::const_iterator I = Entries.find(Section);
161  if (I == Entries.end()) return false;
162  StringMap<Entry>::const_iterator II = I->second.find(Category);
163  if (II == I->second.end()) return false;
164 
165  return II->getValue().match(Query);
166 }
167 
168 } // namespace llvm
std::error_code getError() const
Definition: ErrorOr.h:178
Represents either an error or a value T.
Definition: ErrorOr.h:82
const ValueTy & getValue() const
Definition: StringMap.h:128
iterator find(StringRef Key)
Definition: StringMap.h:265
StringRef getBuffer() const
Definition: MemoryBuffer.h:54
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths)
Parses the special case list entries from files.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition: StringMap.h:291
#define false
Definition: ConvertUTF.c:65
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:591
static bool isLiteralERE(StringRef Str)
If this function returns true, ^Str$ is an extended regular expression that matches Str and only Str...
Definition: Regex.cpp:177
void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters, appending the result fragments to the output list.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:37
std::unique_ptr< Regex > RegEx
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:214
Represents a set of regular expressions.
bool inSection(StringRef Section, StringRef Query, StringRef Category=StringRef()) const
Returns true, if special case list contains a line.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
#define I(x, y, z)
Definition: MD5.cpp:54
static std::unique_ptr< SpecialCaseList > create(const std::vector< std::string > &Paths, std::string &Error)
Parses the special case list entries from files.
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
iterator end()
Definition: StringMap.h:255
reference get()
Definition: ErrorOr.h:175
bool match(StringRef Query) const