Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/SpecialCaseList.cpp
Line
Count
Source (jump to first uncovered line)
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
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"
22
#include <string>
23
#include <system_error>
24
#include <utility>
25
26
#include <stdio.h>
27
namespace llvm {
28
29
bool SpecialCaseList::Matcher::insert(std::string Regexp,
30
153
                                      std::string &REError) {
31
153
  if (
Regex::isLiteralERE(Regexp)153
) {
32
49
    Strings.insert(Regexp);
33
49
    return true;
34
49
  }
35
104
  Trigrams.insert(Regexp);
36
104
37
104
  // Replace * with .*
38
232
  for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
39
128
       
pos += strlen(".*")128
) {
40
128
    Regexp.replace(pos, strlen("*"), ".*");
41
128
  }
42
104
43
104
  // Check that the regexp is valid.
44
104
  Regex CheckRE(Regexp);
45
104
  if (!CheckRE.isValid(REError))
46
2
    return false;
47
102
48
102
  
if (102
!UncompiledRegEx.empty()102
)
49
14
    UncompiledRegEx += "|";
50
153
  UncompiledRegEx += "^(" + Regexp + ")$";
51
153
  return true;
52
153
}
53
54
123
void SpecialCaseList::Matcher::compile() {
55
123
  if (
!UncompiledRegEx.empty()123
) {
56
87
    RegEx.reset(new Regex(UncompiledRegEx));
57
87
    UncompiledRegEx.clear();
58
87
  }
59
123
}
60
61
1.98k
bool SpecialCaseList::Matcher::match(StringRef Query) const {
62
1.98k
  if (Strings.count(Query))
63
49
    return true;
64
1.94k
  
if (1.94k
Trigrams.isDefinitelyOut(Query)1.94k
)
65
584
    return false;
66
1.35k
  
return RegEx && 1.35k
RegEx->match(Query)1.35k
;
67
1.98k
}
68
69
120k
SpecialCaseList::SpecialCaseList() : Sections(), IsCompiled(false) {}
70
71
std::unique_ptr<SpecialCaseList>
72
SpecialCaseList::create(const std::vector<std::string> &Paths,
73
90.5k
                        std::string &Error) {
74
90.5k
  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
75
90.5k
  if (SCL->createInternal(Paths, Error))
76
90.5k
    return SCL;
77
2
  return nullptr;
78
2
}
79
80
std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
81
19
                                                         std::string &Error) {
82
19
  std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
83
19
  if (SCL->createInternal(MB, Error))
84
14
    return SCL;
85
5
  return nullptr;
86
5
}
87
88
std::unique_ptr<SpecialCaseList>
89
59.3k
SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
90
59.3k
  std::string Error;
91
59.3k
  if (auto SCL = create(Paths, Error))
92
59.3k
    return SCL;
93
0
  report_fatal_error(Error);
94
0
}
95
96
bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
97
120k
                                     std::string &Error) {
98
120k
  StringMap<size_t> Sections;
99
55
  for (const auto &Path : Paths) {
100
55
    ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
101
55
        MemoryBuffer::getFile(Path);
102
55
    if (std::error_code 
EC55
= FileOrErr.getError()) {
103
1
      Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
104
1
      return false;
105
1
    }
106
54
    std::string ParseError;
107
54
    if (
!parse(FileOrErr.get().get(), Sections, ParseError)54
) {
108
1
      Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
109
1
      return false;
110
1
    }
111
120k
  }
112
120k
  compile();
113
120k
  return true;
114
120k
}
115
116
bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
117
19
                                     std::string &Error) {
118
19
  StringMap<size_t> Sections;
119
19
  if (!parse(MB, Sections, Error))
120
5
    return false;
121
14
  compile();
122
14
  return true;
123
14
}
124
125
bool SpecialCaseList::parse(const MemoryBuffer *MB,
126
                            StringMap<size_t> &SectionsMap,
127
73
                            std::string &Error) {
128
73
  // Iterate through each line in the blacklist file.
129
73
  SmallVector<StringRef, 16> Lines;
130
73
  SplitString(MB->getBuffer(), Lines, "\n\r");
131
73
132
73
  int LineNo = 1;
133
73
  StringRef Section = "*";
134
182
  for (auto I = Lines.begin(), E = Lines.end(); 
I != E182
;
++I, ++LineNo109
) {
135
115
    // Ignore empty lines and lines starting with "#"
136
115
    if (
I->empty() || 115
I->startswith("#")115
)
137
3
      continue;
138
112
139
112
    // Save section names
140
112
    
if (112
I->startswith("[")112
) {
141
15
      if (
!I->endswith("]")15
) {
142
1
        Error = (Twine("malformed section header on line ") + Twine(LineNo) +
143
1
                 ": " + *I).str();
144
1
        return false;
145
1
      }
146
14
147
14
      Section = I->slice(1, I->size() - 1);
148
14
149
14
      std::string REError;
150
14
      Regex CheckRE(Section);
151
14
      if (
!CheckRE.isValid(REError)14
) {
152
1
        Error =
153
1
            (Twine("malformed regex for section ") + Section + ": '" + REError)
154
1
                .str();
155
1
        return false;
156
1
      }
157
13
158
13
      continue;
159
13
    }
160
97
161
97
    // Get our prefix and unparsed regexp.
162
97
    std::pair<StringRef, StringRef> SplitLine = I->split(":");
163
97
    StringRef Prefix = SplitLine.first;
164
97
    if (
SplitLine.second.empty()97
) {
165
2
      // Missing ':' in the line.
166
2
      Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
167
2
               SplitLine.first + "'").str();
168
2
      return false;
169
2
    }
170
95
171
95
    std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
172
95
    std::string Regexp = SplitRegexp.first;
173
95
    StringRef Category = SplitRegexp.second;
174
95
175
95
    // Create this section if it has not been seen before.
176
95
    if (
SectionsMap.find(Section) == SectionsMap.end()95
) {
177
58
      std::unique_ptr<Matcher> M = make_unique<Matcher>();
178
58
      std::string REError;
179
58
      if (
!M->insert(Section, REError)58
) {
180
0
        Error = (Twine("malformed section ") + Section + ": '" + REError).str();
181
0
        return false;
182
0
      }
183
58
      M->compile();
184
58
185
58
      SectionsMap[Section] = Sections.size();
186
58
      Sections.emplace_back(std::move(M));
187
58
    }
188
95
189
95
    auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
190
95
    std::string REError;
191
95
    if (
!Entry.insert(std::move(Regexp), REError)95
) {
192
2
      Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
193
2
               SplitLine.second + "': " + REError).str();
194
2
      return false;
195
2
    }
196
115
  }
197
67
  return true;
198
73
}
199
200
120k
void SpecialCaseList::compile() {
201
120k
  assert(!IsCompiled && "compile() should only be called once");
202
120k
  // Iterate through every section compiling regular expressions for every query
203
120k
  // and creating Section entries.
204
120k
  for (auto &Section : Sections)
205
55
    for (auto &Prefix : Section.Entries)
206
58
      for (auto &Category : Prefix.getValue())
207
65
        Category.getValue().compile();
208
120k
209
120k
  IsCompiled = true;
210
120k
}
211
212
92.3k
SpecialCaseList::~SpecialCaseList() {}
213
214
bool SpecialCaseList::inSection(StringRef Section, StringRef Prefix,
215
380
                                StringRef Query, StringRef Category) const {
216
380
  assert(IsCompiled && "SpecialCaseList::compile() was not called!");
217
380
218
380
  for (auto &SectionIter : Sections)
219
251
    
if (251
SectionIter.SectionMatcher->match(Section) &&
220
240
        inSection(SectionIter.Entries, Prefix, Query, Category))
221
76
      return true;
222
304
223
304
  return false;
224
304
}
225
226
bool SpecialCaseList::inSection(const SectionEntries &Entries, StringRef Prefix,
227
1.45k
                                StringRef Query, StringRef Category) const {
228
1.45k
  SectionEntries::const_iterator I = Entries.find(Prefix);
229
1.45k
  if (
I == Entries.end()1.45k
)
return false868
;
230
589
  StringMap<Matcher>::const_iterator II = I->second.find(Category);
231
589
  if (
II == I->second.end()589
)
return false203
;
232
386
233
386
  return II->getValue().match(Query);
234
386
}
235
236
}  // namespace llvm