* include/bits/allocator.h (operator==, operator!=): Add exception
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_suppressions.cc
blob14f13e620815290988108001ed27c9d891340e8f
1 //===-- sanitizer_suppressions.cc -----------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Suppression parsing/matching code shared between TSan and LSan.
9 //
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_suppressions.h"
14 #include "sanitizer_allocator_internal.h"
15 #include "sanitizer_common.h"
16 #include "sanitizer_libc.h"
18 namespace __sanitizer {
20 static const char *const kTypeStrings[SuppressionTypeCount] = {
21 "none", "race", "mutex", "thread", "signal", "leak", "called_from_lib"
24 bool TemplateMatch(char *templ, const char *str) {
25 if (str == 0 || str[0] == 0)
26 return false;
27 bool start = false;
28 if (templ && templ[0] == '^') {
29 start = true;
30 templ++;
32 bool asterisk = false;
33 while (templ && templ[0]) {
34 if (templ[0] == '*') {
35 templ++;
36 start = false;
37 asterisk = true;
38 continue;
40 if (templ[0] == '$')
41 return str[0] == 0 || asterisk;
42 if (str[0] == 0)
43 return false;
44 char *tpos = (char*)internal_strchr(templ, '*');
45 char *tpos1 = (char*)internal_strchr(templ, '$');
46 if (tpos == 0 || (tpos1 && tpos1 < tpos))
47 tpos = tpos1;
48 if (tpos != 0)
49 tpos[0] = 0;
50 const char *str0 = str;
51 const char *spos = internal_strstr(str, templ);
52 str = spos + internal_strlen(templ);
53 templ = tpos;
54 if (tpos)
55 tpos[0] = tpos == tpos1 ? '$' : '*';
56 if (spos == 0)
57 return false;
58 if (start && spos != str0)
59 return false;
60 start = false;
61 asterisk = false;
63 return true;
66 bool SuppressionContext::Match(const char *str, SuppressionType type,
67 Suppression **s) {
68 can_parse_ = false;
69 uptr i;
70 for (i = 0; i < suppressions_.size(); i++)
71 if (type == suppressions_[i].type &&
72 TemplateMatch(suppressions_[i].templ, str))
73 break;
74 if (i == suppressions_.size()) return false;
75 *s = &suppressions_[i];
76 return true;
79 static const char *StripPrefix(const char *str, const char *prefix) {
80 while (str && *str == *prefix) {
81 str++;
82 prefix++;
84 if (!*prefix)
85 return str;
86 return 0;
89 void SuppressionContext::Parse(const char *str) {
90 // Context must not mutate once Match has been called.
91 CHECK(can_parse_);
92 const char *line = str;
93 while (line) {
94 while (line[0] == ' ' || line[0] == '\t')
95 line++;
96 const char *end = internal_strchr(line, '\n');
97 if (end == 0)
98 end = line + internal_strlen(line);
99 if (line != end && line[0] != '#') {
100 const char *end2 = end;
101 while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
102 end2--;
103 int type;
104 for (type = 0; type < SuppressionTypeCount; type++) {
105 const char *next_char = StripPrefix(line, kTypeStrings[type]);
106 if (next_char && *next_char == ':') {
107 line = ++next_char;
108 break;
111 if (type == SuppressionTypeCount) {
112 Printf("%s: failed to parse suppressions\n", SanitizerToolName);
113 Die();
115 Suppression s;
116 s.type = static_cast<SuppressionType>(type);
117 s.templ = (char*)InternalAlloc(end2 - line + 1);
118 internal_memcpy(s.templ, line, end2 - line);
119 s.templ[end2 - line] = 0;
120 s.hit_count = 0;
121 s.weight = 0;
122 suppressions_.push_back(s);
124 if (end[0] == 0)
125 break;
126 line = end + 1;
130 uptr SuppressionContext::SuppressionCount() const {
131 return suppressions_.size();
134 const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
135 CHECK_LT(i, suppressions_.size());
136 return &suppressions_[i];
139 void SuppressionContext::GetMatched(
140 InternalMmapVector<Suppression *> *matched) {
141 for (uptr i = 0; i < suppressions_.size(); i++)
142 if (suppressions_[i].hit_count)
143 matched->push_back(&suppressions_[i]);
146 const char *SuppressionTypeString(SuppressionType t) {
147 CHECK(t < SuppressionTypeCount);
148 return kTypeStrings[t];
151 } // namespace __sanitizer