SpecialCaseList.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //===----------------------------------------------------------------------===//
  12. //
  13. // This is a utility class used to parse user-provided text files with
  14. // "special case lists" for code sanitizers. Such files are used to
  15. // define an "ABI list" for DataFlowSanitizer and allow/exclusion lists for
  16. // sanitizers like AddressSanitizer or UndefinedBehaviorSanitizer.
  17. //
  18. // Empty lines and lines starting with "#" are ignored. Sections are defined
  19. // using a '[section_name]' header and can be used to specify sanitizers the
  20. // entries below it apply to. Section names are regular expressions, and
  21. // entries without a section header match all sections (e.g. an '[*]' header
  22. // is assumed.)
  23. // The remaining lines should have the form:
  24. // prefix:wildcard_expression[=category]
  25. // If category is not specified, it is assumed to be empty string.
  26. // Definitions of "prefix" and "category" are sanitizer-specific. For example,
  27. // sanitizer exclusion support prefixes "src", "mainfile", "fun" and "global".
  28. // Wildcard expressions define, respectively, source files, main files,
  29. // functions or globals which shouldn't be instrumented.
  30. // Examples of categories:
  31. // "functional": used in DFSan to list functions with pure functional
  32. // semantics.
  33. // "init": used in ASan exclusion list to disable initialization-order bugs
  34. // detection for certain globals or source files.
  35. // Full special case list file example:
  36. // ---
  37. // [address]
  38. // # Excluded items:
  39. // fun:*_ZN4base6subtle*
  40. // global:*global_with_bad_access_or_initialization*
  41. // global:*global_with_initialization_issues*=init
  42. // type:*Namespace::ClassName*=init
  43. // src:file_with_tricky_code.cc
  44. // src:ignore-global-initializers-issues.cc=init
  45. // mainfile:main_file.cc
  46. //
  47. // [dataflow]
  48. // # Functions with pure functional semantics:
  49. // fun:cos=functional
  50. // fun:sin=functional
  51. // ---
  52. // Note that the wild card is in fact an llvm::Regex, but * is automatically
  53. // replaced with .*
  54. //
  55. //===----------------------------------------------------------------------===//
  56. #ifndef LLVM_SUPPORT_SPECIALCASELIST_H
  57. #define LLVM_SUPPORT_SPECIALCASELIST_H
  58. #include "llvm/ADT/StringMap.h"
  59. #include "llvm/Support/Regex.h"
  60. #include "llvm/Support/TrigramIndex.h"
  61. #include <memory>
  62. #include <string>
  63. #include <vector>
  64. namespace llvm {
  65. class MemoryBuffer;
  66. class StringRef;
  67. namespace vfs {
  68. class FileSystem;
  69. }
  70. class SpecialCaseList {
  71. public:
  72. /// Parses the special case list entries from files. On failure, returns
  73. /// 0 and writes an error message to string.
  74. static std::unique_ptr<SpecialCaseList>
  75. create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &FS,
  76. std::string &Error);
  77. /// Parses the special case list from a memory buffer. On failure, returns
  78. /// 0 and writes an error message to string.
  79. static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB,
  80. std::string &Error);
  81. /// Parses the special case list entries from files. On failure, reports a
  82. /// fatal error.
  83. static std::unique_ptr<SpecialCaseList>
  84. createOrDie(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &FS);
  85. ~SpecialCaseList();
  86. /// Returns true, if special case list contains a line
  87. /// \code
  88. /// @Prefix:<E>=@Category
  89. /// \endcode
  90. /// where @Query satisfies wildcard expression <E> in a given @Section.
  91. bool inSection(StringRef Section, StringRef Prefix, StringRef Query,
  92. StringRef Category = StringRef()) const;
  93. /// Returns the line number corresponding to the special case list entry if
  94. /// the special case list contains a line
  95. /// \code
  96. /// @Prefix:<E>=@Category
  97. /// \endcode
  98. /// where @Query satisfies wildcard expression <E> in a given @Section.
  99. /// Returns zero if there is no exclusion entry corresponding to this
  100. /// expression.
  101. unsigned inSectionBlame(StringRef Section, StringRef Prefix, StringRef Query,
  102. StringRef Category = StringRef()) const;
  103. protected:
  104. // Implementations of the create*() functions that can also be used by derived
  105. // classes.
  106. bool createInternal(const std::vector<std::string> &Paths,
  107. vfs::FileSystem &VFS, std::string &Error);
  108. bool createInternal(const MemoryBuffer *MB, std::string &Error);
  109. SpecialCaseList() = default;
  110. SpecialCaseList(SpecialCaseList const &) = delete;
  111. SpecialCaseList &operator=(SpecialCaseList const &) = delete;
  112. /// Represents a set of regular expressions. Regular expressions which are
  113. /// "literal" (i.e. no regex metacharacters) are stored in Strings. The
  114. /// reason for doing so is efficiency; StringMap is much faster at matching
  115. /// literal strings than Regex.
  116. class Matcher {
  117. public:
  118. bool insert(std::string Regexp, unsigned LineNumber, std::string &REError);
  119. // Returns the line number in the source file that this query matches to.
  120. // Returns zero if no match is found.
  121. unsigned match(StringRef Query) const;
  122. private:
  123. StringMap<unsigned> Strings;
  124. TrigramIndex Trigrams;
  125. std::vector<std::pair<std::unique_ptr<Regex>, unsigned>> RegExes;
  126. };
  127. using SectionEntries = StringMap<StringMap<Matcher>>;
  128. struct Section {
  129. Section(std::unique_ptr<Matcher> M) : SectionMatcher(std::move(M)){};
  130. std::unique_ptr<Matcher> SectionMatcher;
  131. SectionEntries Entries;
  132. };
  133. std::vector<Section> Sections;
  134. /// Parses just-constructed SpecialCaseList entries from a memory buffer.
  135. bool parse(const MemoryBuffer *MB, StringMap<size_t> &SectionsMap,
  136. std::string &Error);
  137. // Helper method for derived classes to search by Prefix, Query, and Category
  138. // once they have already resolved a section entry.
  139. unsigned inSectionBlame(const SectionEntries &Entries, StringRef Prefix,
  140. StringRef Query, StringRef Category) const;
  141. };
  142. } // namespace llvm
  143. #endif // LLVM_SUPPORT_SPECIALCASELIST_H
  144. #ifdef __GNUC__
  145. #pragma GCC diagnostic pop
  146. #endif