• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- sanitizer_suppressions.cc -----------------------------------------===//
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 // Suppression parsing/matching code shared between TSan and LSan.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "sanitizer_suppressions.h"
15 
16 #include "sanitizer_allocator_internal.h"
17 #include "sanitizer_common.h"
18 #include "sanitizer_libc.h"
19 
20 namespace __sanitizer {
21 
22 static const char *const kTypeStrings[SuppressionTypeCount] = {
23     "none",   "race", "mutex",           "thread",
24     "signal", "leak", "called_from_lib", "deadlock"};
25 
TemplateMatch(char * templ,const char * str)26 bool TemplateMatch(char *templ, const char *str) {
27   if (str == 0 || str[0] == 0)
28     return false;
29   bool start = false;
30   if (templ && templ[0] == '^') {
31     start = true;
32     templ++;
33   }
34   bool asterisk = false;
35   while (templ && templ[0]) {
36     if (templ[0] == '*') {
37       templ++;
38       start = false;
39       asterisk = true;
40       continue;
41     }
42     if (templ[0] == '$')
43       return str[0] == 0 || asterisk;
44     if (str[0] == 0)
45       return false;
46     char *tpos = (char*)internal_strchr(templ, '*');
47     char *tpos1 = (char*)internal_strchr(templ, '$');
48     if (tpos == 0 || (tpos1 && tpos1 < tpos))
49       tpos = tpos1;
50     if (tpos != 0)
51       tpos[0] = 0;
52     const char *str0 = str;
53     const char *spos = internal_strstr(str, templ);
54     str = spos + internal_strlen(templ);
55     templ = tpos;
56     if (tpos)
57       tpos[0] = tpos == tpos1 ? '$' : '*';
58     if (spos == 0)
59       return false;
60     if (start && spos != str0)
61       return false;
62     start = false;
63     asterisk = false;
64   }
65   return true;
66 }
67 
Match(const char * str,SuppressionType type,Suppression ** s)68 bool SuppressionContext::Match(const char *str, SuppressionType type,
69                                Suppression **s) {
70   can_parse_ = false;
71   uptr i;
72   for (i = 0; i < suppressions_.size(); i++)
73     if (type == suppressions_[i].type &&
74         TemplateMatch(suppressions_[i].templ, str))
75       break;
76   if (i == suppressions_.size()) return false;
77   *s = &suppressions_[i];
78   return true;
79 }
80 
StripPrefix(const char * str,const char * prefix)81 static const char *StripPrefix(const char *str, const char *prefix) {
82   while (str && *str == *prefix) {
83     str++;
84     prefix++;
85   }
86   if (!*prefix)
87     return str;
88   return 0;
89 }
90 
Parse(const char * str)91 void SuppressionContext::Parse(const char *str) {
92   // Context must not mutate once Match has been called.
93   CHECK(can_parse_);
94   const char *line = str;
95   while (line) {
96     while (line[0] == ' ' || line[0] == '\t')
97       line++;
98     const char *end = internal_strchr(line, '\n');
99     if (end == 0)
100       end = line + internal_strlen(line);
101     if (line != end && line[0] != '#') {
102       const char *end2 = end;
103       while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
104         end2--;
105       int type;
106       for (type = 0; type < SuppressionTypeCount; type++) {
107         const char *next_char = StripPrefix(line, kTypeStrings[type]);
108         if (next_char && *next_char == ':') {
109           line = ++next_char;
110           break;
111         }
112       }
113       if (type == SuppressionTypeCount) {
114         Printf("%s: failed to parse suppressions\n", SanitizerToolName);
115         Die();
116       }
117       Suppression s;
118       s.type = static_cast<SuppressionType>(type);
119       s.templ = (char*)InternalAlloc(end2 - line + 1);
120       internal_memcpy(s.templ, line, end2 - line);
121       s.templ[end2 - line] = 0;
122       s.hit_count = 0;
123       s.weight = 0;
124       suppressions_.push_back(s);
125     }
126     if (end[0] == 0)
127       break;
128     line = end + 1;
129   }
130 }
131 
SuppressionCount() const132 uptr SuppressionContext::SuppressionCount() const {
133   return suppressions_.size();
134 }
135 
SuppressionAt(uptr i) const136 const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
137   CHECK_LT(i, suppressions_.size());
138   return &suppressions_[i];
139 }
140 
GetMatched(InternalMmapVector<Suppression * > * matched)141 void SuppressionContext::GetMatched(
142     InternalMmapVector<Suppression *> *matched) {
143   for (uptr i = 0; i < suppressions_.size(); i++)
144     if (suppressions_[i].hit_count)
145       matched->push_back(&suppressions_[i]);
146 }
147 
SuppressionTypeString(SuppressionType t)148 const char *SuppressionTypeString(SuppressionType t) {
149   CHECK(t < SuppressionTypeCount);
150   return kTypeStrings[t];
151 }
152 
153 }  // namespace __sanitizer
154