1a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev//===-- sanitizer_suppressions.cc -----------------------------------------===// 2a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// 3a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// The LLVM Compiler Infrastructure 4a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// 5a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// This file is distributed under the University of Illinois Open Source 6a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// License. See LICENSE.TXT for details. 7a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// 8a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev//===----------------------------------------------------------------------===// 9a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// 10a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// Suppression parsing/matching code shared between TSan and LSan. 11a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev// 12a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev//===----------------------------------------------------------------------===// 13a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 14a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev#include "sanitizer_suppressions.h" 15a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 16a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev#include "sanitizer_allocator_internal.h" 17a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev#include "sanitizer_common.h" 18a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev#include "sanitizer_libc.h" 19a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 20a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevnamespace __sanitizer { 21a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 22a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevstatic const char *const kTypeStrings[SuppressionTypeCount] = { 23b33cfeb6004d3a93e6d35749c14db0190c6c2b4cSergey Matveev "none", "race", "mutex", "thread", "signal", "leak" 24a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev}; 25a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 26a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevbool TemplateMatch(char *templ, const char *str) { 27a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (str == 0 || str[0] == 0) 28a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return false; 2955e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov bool start = false; 3055e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov if (templ && templ[0] == '^') { 3155e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov start = true; 3255e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov templ++; 3355e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov } 3455e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov bool asterisk = false; 35a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev while (templ && templ[0]) { 36a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (templ[0] == '*') { 37a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev templ++; 3855e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov start = false; 3955e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov asterisk = true; 40a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev continue; 41a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 4255e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov if (templ[0] == '$') 4355e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov return str[0] == 0 || asterisk; 44a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (str[0] == 0) 45a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return false; 4655e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov char *tpos = (char*)internal_strchr(templ, '*'); 4755e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov char *tpos1 = (char*)internal_strchr(templ, '$'); 4855e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov if (tpos == 0 || (tpos1 && tpos1 < tpos)) 4955e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov tpos = tpos1; 50a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (tpos != 0) 51a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev tpos[0] = 0; 5255e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov const char *str0 = str; 5355e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov const char *spos = internal_strstr(str, templ); 54a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev str = spos + internal_strlen(templ); 55a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev templ = tpos; 56a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (tpos) 5755e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov tpos[0] = tpos == tpos1 ? '$' : '*'; 58a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (spos == 0) 59a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return false; 6055e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov if (start && spos != str0) 6155e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov return false; 6255e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov start = false; 6355e6f3f4e6b799e0affd13f28137661f8707133fDmitry Vyukov asterisk = false; 64a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 65a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return true; 66a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 67a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 68a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevbool SuppressionContext::Match(const char *str, SuppressionType type, 69a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev Suppression **s) { 70a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev can_parse_ = false; 71a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev uptr i; 72a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev for (i = 0; i < suppressions_.size(); i++) 73a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (type == suppressions_[i].type && 74a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev TemplateMatch(suppressions_[i].templ, str)) 75a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev break; 76a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (i == suppressions_.size()) return false; 77a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev *s = &suppressions_[i]; 78a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return true; 79a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 80a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 81a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevstatic const char *StripPrefix(const char *str, const char *prefix) { 82a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev while (str && *str == *prefix) { 83a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev str++; 84a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev prefix++; 85a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 86a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (!*prefix) 87a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return str; 88a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return 0; 89a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 90a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 91a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevvoid SuppressionContext::Parse(const char *str) { 92a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev // Context must not mutate once Match has been called. 93a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev CHECK(can_parse_); 94a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev const char *line = str; 95a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev while (line) { 96a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev while (line[0] == ' ' || line[0] == '\t') 97a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev line++; 98a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev const char *end = internal_strchr(line, '\n'); 99a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (end == 0) 100a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev end = line + internal_strlen(line); 101a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (line != end && line[0] != '#') { 102a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev const char *end2 = end; 103a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t')) 104a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev end2--; 105a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev int type; 106a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev for (type = 0; type < SuppressionTypeCount; type++) { 107a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev const char *next_char = StripPrefix(line, kTypeStrings[type]); 108a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (next_char && *next_char == ':') { 109a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev line = ++next_char; 110a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev break; 111a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 112a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 113a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (type == SuppressionTypeCount) { 114b33cfeb6004d3a93e6d35749c14db0190c6c2b4cSergey Matveev Printf("%s: failed to parse suppressions\n", SanitizerToolName); 115a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev Die(); 116a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 117a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev Suppression s; 118a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev s.type = static_cast<SuppressionType>(type); 119a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev s.templ = (char*)InternalAlloc(end2 - line + 1); 120a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev internal_memcpy(s.templ, line, end2 - line); 121a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev s.templ[end2 - line] = 0; 122a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev s.hit_count = 0; 123b33cfeb6004d3a93e6d35749c14db0190c6c2b4cSergey Matveev s.weight = 0; 124a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev suppressions_.push_back(s); 125a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 126a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (end[0] == 0) 127a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev break; 128a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev line = end + 1; 129a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev } 130a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 131a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 132a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevuptr SuppressionContext::SuppressionCount() { 133a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return suppressions_.size(); 134a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 135a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 136a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevvoid SuppressionContext::GetMatched( 137a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev InternalMmapVector<Suppression *> *matched) { 138a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev for (uptr i = 0; i < suppressions_.size(); i++) 139a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev if (suppressions_[i].hit_count) 140a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev matched->push_back(&suppressions_[i]); 141a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 142a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 143a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveevconst char *SuppressionTypeString(SuppressionType t) { 144a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev CHECK(t < SuppressionTypeCount); 145a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev return kTypeStrings[t]; 146a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} 147a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev 148a52e5c6f371bcc66e89792db1219a557664aab8dSergey Matveev} // namespace __sanitizer 149