1 //===-- sanitizer_suppressions.cc -----------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Suppression parsing/matching code.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_suppressions.h"
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"
22 namespace __sanitizer {
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),
29 CHECK_LE(suppression_types_num_, kMaxSuppressionTypes);
30 internal_memset(has_suppression_type_, 0, suppression_types_num_);
33 void SuppressionContext::ParseFromFile(const char *filename) {
34 if (filename[0] == '\0')
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,
48 bool SuppressionContext::Match(const char *str, const char *type,
51 if (!HasSuppressionType(type))
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)) {
63 static const char *StripPrefix(const char *str, const char *prefix) {
64 while (str && *str == *prefix) {
73 void SuppressionContext::Parse(const char *str) {
74 // Context must not mutate once Match has been called.
76 const char *line = str;
78 while (line[0] == ' ' || line[0] == '\t')
80 const char *end = internal_strchr(line, '\n');
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'))
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 == ':') {
95 if (type == suppression_types_num_) {
96 Printf("%s: failed to parse suppressions\n", SanitizerToolName);
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;
106 suppressions_.push_back(s);
107 has_suppression_type_[type] = true;
115 uptr SuppressionContext::SuppressionCount() const {
116 return suppressions_.size();
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];
127 const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
128 CHECK_LT(i, suppressions_.size());
129 return &suppressions_[i];
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]);
139 } // namespace __sanitizer