SpecialCaseList.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. //===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This is a utility class for instrumentation passes (like AddressSanitizer
  10. // or ThreadSanitizer) to avoid instrumenting some functions or global
  11. // variables, or to instrument some functions or global variables in a specific
  12. // way, based on a user-supplied list.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "llvm/Support/SpecialCaseList.h"
  16. #include "llvm/ADT/SmallVector.h"
  17. #include "llvm/Support/MemoryBuffer.h"
  18. #include "llvm/Support/Regex.h"
  19. #include "llvm/Support/VirtualFileSystem.h"
  20. #include <string>
  21. #include <system_error>
  22. #include <utility>
  23. #include <stdio.h>
  24. namespace llvm {
  25. bool SpecialCaseList::Matcher::insert(std::string Regexp,
  26. unsigned LineNumber,
  27. std::string &REError) {
  28. if (Regexp.empty()) {
  29. REError = "Supplied regexp was blank";
  30. return false;
  31. }
  32. if (Regex::isLiteralERE(Regexp)) {
  33. Strings[Regexp] = LineNumber;
  34. return true;
  35. }
  36. Trigrams.insert(Regexp);
  37. // Replace * with .*
  38. for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
  39. pos += strlen(".*")) {
  40. Regexp.replace(pos, strlen("*"), ".*");
  41. }
  42. Regexp = (Twine("^(") + StringRef(Regexp) + ")$").str();
  43. // Check that the regexp is valid.
  44. Regex CheckRE(Regexp);
  45. if (!CheckRE.isValid(REError))
  46. return false;
  47. RegExes.emplace_back(
  48. std::make_pair(std::make_unique<Regex>(std::move(CheckRE)), LineNumber));
  49. return true;
  50. }
  51. unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
  52. auto It = Strings.find(Query);
  53. if (It != Strings.end())
  54. return It->second;
  55. if (Trigrams.isDefinitelyOut(Query))
  56. return false;
  57. for (const auto &RegExKV : RegExes)
  58. if (RegExKV.first->match(Query))
  59. return RegExKV.second;
  60. return 0;
  61. }
  62. std::unique_ptr<SpecialCaseList>
  63. SpecialCaseList::create(const std::vector<std::string> &Paths,
  64. llvm::vfs::FileSystem &FS, std::string &Error) {
  65. std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
  66. if (SCL->createInternal(Paths, FS, Error))
  67. return SCL;
  68. return nullptr;
  69. }
  70. std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
  71. std::string &Error) {
  72. std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
  73. if (SCL->createInternal(MB, Error))
  74. return SCL;
  75. return nullptr;
  76. }
  77. std::unique_ptr<SpecialCaseList>
  78. SpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
  79. llvm::vfs::FileSystem &FS) {
  80. std::string Error;
  81. if (auto SCL = create(Paths, FS, Error))
  82. return SCL;
  83. report_fatal_error(Twine(Error));
  84. }
  85. bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
  86. vfs::FileSystem &VFS, std::string &Error) {
  87. StringMap<size_t> Sections;
  88. for (const auto &Path : Paths) {
  89. ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
  90. VFS.getBufferForFile(Path);
  91. if (std::error_code EC = FileOrErr.getError()) {
  92. Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
  93. return false;
  94. }
  95. std::string ParseError;
  96. if (!parse(FileOrErr.get().get(), Sections, ParseError)) {
  97. Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
  98. return false;
  99. }
  100. }
  101. return true;
  102. }
  103. bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
  104. std::string &Error) {
  105. StringMap<size_t> Sections;
  106. if (!parse(MB, Sections, Error))
  107. return false;
  108. return true;
  109. }
  110. bool SpecialCaseList::parse(const MemoryBuffer *MB,
  111. StringMap<size_t> &SectionsMap,
  112. std::string &Error) {
  113. // Iterate through each line in the exclusion list file.
  114. SmallVector<StringRef, 16> Lines;
  115. MB->getBuffer().split(Lines, '\n');
  116. unsigned LineNo = 1;
  117. StringRef Section = "*";
  118. for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
  119. *I = I->trim();
  120. // Ignore empty lines and lines starting with "#"
  121. if (I->empty() || I->startswith("#"))
  122. continue;
  123. // Save section names
  124. if (I->startswith("[")) {
  125. if (!I->endswith("]")) {
  126. Error = (Twine("malformed section header on line ") + Twine(LineNo) +
  127. ": " + *I).str();
  128. return false;
  129. }
  130. Section = I->slice(1, I->size() - 1);
  131. std::string REError;
  132. Regex CheckRE(Section);
  133. if (!CheckRE.isValid(REError)) {
  134. Error =
  135. (Twine("malformed regex for section ") + Section + ": '" + REError)
  136. .str();
  137. return false;
  138. }
  139. continue;
  140. }
  141. // Get our prefix and unparsed regexp.
  142. std::pair<StringRef, StringRef> SplitLine = I->split(":");
  143. StringRef Prefix = SplitLine.first;
  144. if (SplitLine.second.empty()) {
  145. // Missing ':' in the line.
  146. Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
  147. SplitLine.first + "'").str();
  148. return false;
  149. }
  150. std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
  151. std::string Regexp = std::string(SplitRegexp.first);
  152. StringRef Category = SplitRegexp.second;
  153. // Create this section if it has not been seen before.
  154. if (SectionsMap.find(Section) == SectionsMap.end()) {
  155. std::unique_ptr<Matcher> M = std::make_unique<Matcher>();
  156. std::string REError;
  157. if (!M->insert(std::string(Section), LineNo, REError)) {
  158. Error = (Twine("malformed section ") + Section + ": '" + REError).str();
  159. return false;
  160. }
  161. SectionsMap[Section] = Sections.size();
  162. Sections.emplace_back(std::move(M));
  163. }
  164. auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
  165. std::string REError;
  166. if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
  167. Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
  168. SplitLine.second + "': " + REError).str();
  169. return false;
  170. }
  171. }
  172. return true;
  173. }
  174. SpecialCaseList::~SpecialCaseList() {}
  175. bool SpecialCaseList::inSection(StringRef Section, StringRef Prefix,
  176. StringRef Query, StringRef Category) const {
  177. return inSectionBlame(Section, Prefix, Query, Category);
  178. }
  179. unsigned SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
  180. StringRef Query,
  181. StringRef Category) const {
  182. for (const auto &SectionIter : Sections)
  183. if (SectionIter.SectionMatcher->match(Section)) {
  184. unsigned Blame =
  185. inSectionBlame(SectionIter.Entries, Prefix, Query, Category);
  186. if (Blame)
  187. return Blame;
  188. }
  189. return 0;
  190. }
  191. unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,
  192. StringRef Prefix, StringRef Query,
  193. StringRef Category) const {
  194. SectionEntries::const_iterator I = Entries.find(Prefix);
  195. if (I == Entries.end()) return 0;
  196. StringMap<Matcher>::const_iterator II = I->second.find(Category);
  197. if (II == I->second.end()) return 0;
  198. return II->getValue().match(Query);
  199. }
  200. } // namespace llvm