sanitizer_suppressions.cc revision b33cfeb6004d3a93e6d35749c14db0190c6c2b4c
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 20namespace __sanitizer { 21 22static const char *const kTypeStrings[SuppressionTypeCount] = { 23 "none", "race", "mutex", "thread", "signal", "leak" 24}; 25 26bool TemplateMatch(char *templ, const char *str) { 27 if (str == 0 || str[0] == 0) 28 return false; 29 char *tpos; 30 const char *spos; 31 while (templ && templ[0]) { 32 if (templ[0] == '*') { 33 templ++; 34 continue; 35 } 36 if (str[0] == 0) 37 return false; 38 tpos = (char*)internal_strchr(templ, '*'); 39 if (tpos != 0) 40 tpos[0] = 0; 41 spos = internal_strstr(str, templ); 42 str = spos + internal_strlen(templ); 43 templ = tpos; 44 if (tpos) 45 tpos[0] = '*'; 46 if (spos == 0) 47 return false; 48 } 49 return true; 50} 51 52bool SuppressionContext::Match(const char *str, SuppressionType type, 53 Suppression **s) { 54 can_parse_ = false; 55 uptr i; 56 for (i = 0; i < suppressions_.size(); i++) 57 if (type == suppressions_[i].type && 58 TemplateMatch(suppressions_[i].templ, str)) 59 break; 60 if (i == suppressions_.size()) return false; 61 *s = &suppressions_[i]; 62 return true; 63} 64 65static const char *StripPrefix(const char *str, const char *prefix) { 66 while (str && *str == *prefix) { 67 str++; 68 prefix++; 69 } 70 if (!*prefix) 71 return str; 72 return 0; 73} 74 75void SuppressionContext::Parse(const char *str) { 76 // Context must not mutate once Match has been called. 77 CHECK(can_parse_); 78 const char *line = str; 79 while (line) { 80 while (line[0] == ' ' || line[0] == '\t') 81 line++; 82 const char *end = internal_strchr(line, '\n'); 83 if (end == 0) 84 end = line + internal_strlen(line); 85 if (line != end && line[0] != '#') { 86 const char *end2 = end; 87 while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t')) 88 end2--; 89 int type; 90 for (type = 0; type < SuppressionTypeCount; type++) { 91 const char *next_char = StripPrefix(line, kTypeStrings[type]); 92 if (next_char && *next_char == ':') { 93 line = ++next_char; 94 break; 95 } 96 } 97 if (type == SuppressionTypeCount) { 98 Printf("%s: failed to parse suppressions\n", SanitizerToolName); 99 Die(); 100 } 101 Suppression s; 102 s.type = static_cast<SuppressionType>(type); 103 s.templ = (char*)InternalAlloc(end2 - line + 1); 104 internal_memcpy(s.templ, line, end2 - line); 105 s.templ[end2 - line] = 0; 106 s.hit_count = 0; 107 s.weight = 0; 108 suppressions_.push_back(s); 109 } 110 if (end[0] == 0) 111 break; 112 line = end + 1; 113 } 114} 115 116uptr SuppressionContext::SuppressionCount() { 117 return suppressions_.size(); 118} 119 120void SuppressionContext::GetMatched( 121 InternalMmapVector<Suppression *> *matched) { 122 for (uptr i = 0; i < suppressions_.size(); i++) 123 if (suppressions_[i].hit_count) 124 matched->push_back(&suppressions_[i]); 125} 126 127const char *SuppressionTypeString(SuppressionType t) { 128 CHECK(t < SuppressionTypeCount); 129 return kTypeStrings[t]; 130} 131 132} // namespace __sanitizer 133