]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
Update llvm/clang to r242221.
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_suppressions.cc
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.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "sanitizer_suppressions.h"
15
16 #include "sanitizer_allocator_internal.h"
17 #include "sanitizer_common.h"
18 #include "sanitizer_flags.h"
19 #include "sanitizer_libc.h"
20 #include "sanitizer_placement_new.h"
21
22 namespace __sanitizer {
23
24 SuppressionContext::SuppressionContext(const char *suppression_types[],
25                                        int suppression_types_num)
26     : suppression_types_(suppression_types),
27       suppression_types_num_(suppression_types_num), suppressions_(1),
28       can_parse_(true) {
29   CHECK_LE(suppression_types_num_, kMaxSuppressionTypes);
30   internal_memset(has_suppression_type_, 0, suppression_types_num_);
31 }
32
33 void SuppressionContext::ParseFromFile(const char *filename) {
34   if (filename[0] == '\0')
35     return;
36   char *file_contents;
37   uptr buffer_size;
38   uptr contents_size = ReadFileToBuffer(filename, &file_contents, &buffer_size,
39                                         1 << 26 /* max_len */);
40   if (contents_size == 0) {
41     Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
42            filename);
43     Die();
44   }
45   Parse(file_contents);
46 }
47
48 bool SuppressionContext::Match(const char *str, const char *type,
49                                Suppression **s) {
50   can_parse_ = false;
51   if (!HasSuppressionType(type))
52     return false;
53   for (uptr i = 0; i < suppressions_.size(); i++) {
54     Suppression &cur = suppressions_[i];
55     if (0 == internal_strcmp(cur.type, type) && TemplateMatch(cur.templ, str)) {
56       *s = &cur;
57       return true;
58     }
59   }
60   return false;
61 }
62
63 static const char *StripPrefix(const char *str, const char *prefix) {
64   while (str && *str == *prefix) {
65     str++;
66     prefix++;
67   }
68   if (!*prefix)
69     return str;
70   return 0;
71 }
72
73 void SuppressionContext::Parse(const char *str) {
74   // Context must not mutate once Match has been called.
75   CHECK(can_parse_);
76   const char *line = str;
77   while (line) {
78     while (line[0] == ' ' || line[0] == '\t')
79       line++;
80     const char *end = internal_strchr(line, '\n');
81     if (end == 0)
82       end = line + internal_strlen(line);
83     if (line != end && line[0] != '#') {
84       const char *end2 = end;
85       while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
86         end2--;
87       int type;
88       for (type = 0; type < suppression_types_num_; type++) {
89         const char *next_char = StripPrefix(line, suppression_types_[type]);
90         if (next_char && *next_char == ':') {
91           line = ++next_char;
92           break;
93         }
94       }
95       if (type == suppression_types_num_) {
96         Printf("%s: failed to parse suppressions\n", SanitizerToolName);
97         Die();
98       }
99       Suppression s;
100       s.type = suppression_types_[type];
101       s.templ = (char*)InternalAlloc(end2 - line + 1);
102       internal_memcpy(s.templ, line, end2 - line);
103       s.templ[end2 - line] = 0;
104       s.hit_count = 0;
105       s.weight = 0;
106       suppressions_.push_back(s);
107       has_suppression_type_[type] = true;
108     }
109     if (end[0] == 0)
110       break;
111     line = end + 1;
112   }
113 }
114
115 uptr SuppressionContext::SuppressionCount() const {
116   return suppressions_.size();
117 }
118
119 bool SuppressionContext::HasSuppressionType(const char *type) const {
120   for (int i = 0; i < suppression_types_num_; i++) {
121     if (0 == internal_strcmp(type, suppression_types_[i]))
122       return has_suppression_type_[i];
123   }
124   return false;
125 }
126
127 const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
128   CHECK_LT(i, suppressions_.size());
129   return &suppressions_[i];
130 }
131
132 void SuppressionContext::GetMatched(
133     InternalMmapVector<Suppression *> *matched) {
134   for (uptr i = 0; i < suppressions_.size(); i++)
135     if (suppressions_[i].hit_count)
136       matched->push_back(&suppressions_[i]);
137 }
138
139 }  // namespace __sanitizer