SpecialCaseList.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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", "fun" and "global".
  28. // Wildcard expressions define, respectively, source files, functions or
  29. // 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. //
  46. // [dataflow]
  47. // # Functions with pure functional semantics:
  48. // fun:cos=functional
  49. // fun:sin=functional
  50. // ---
  51. // Note that the wild card is in fact an llvm::Regex, but * is automatically
  52. // replaced with .*
  53. //
  54. //===----------------------------------------------------------------------===//
  55. #ifndef LLVM_SUPPORT_SPECIALCASELIST_H
  56. #define LLVM_SUPPORT_SPECIALCASELIST_H
  57. #include "llvm/ADT/StringMap.h"
  58. #include "llvm/Support/Regex.h"
  59. #include "llvm/Support/TrigramIndex.h"
  60. #include <memory>
  61. #include <string>
  62. #include <vector>
  63. namespace llvm {
  64. class MemoryBuffer;
  65. class StringRef;
  66. namespace vfs {
  67. class FileSystem;
  68. }
  69. class SpecialCaseList {
  70. public:
  71. /// Parses the special case list entries from files. On failure, returns
  72. /// 0 and writes an error message to string.
  73. static std::unique_ptr<SpecialCaseList>
  74. create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &FS,
  75. std::string &Error);
  76. /// Parses the special case list from a memory buffer. On failure, returns
  77. /// 0 and writes an error message to string.
  78. static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB,
  79. std::string &Error);
  80. /// Parses the special case list entries from files. On failure, reports a
  81. /// fatal error.
  82. static std::unique_ptr<SpecialCaseList>
  83. createOrDie(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &FS);
  84. ~SpecialCaseList();
  85. /// Returns true, if special case list contains a line
  86. /// \code
  87. /// @Prefix:<E>=@Category
  88. /// \endcode
  89. /// where @Query satisfies wildcard expression <E> in a given @Section.
  90. bool inSection(StringRef Section, StringRef Prefix, StringRef Query,
  91. StringRef Category = StringRef()) const;
  92. /// Returns the line number corresponding to the special case list entry if
  93. /// the special case list contains a line
  94. /// \code
  95. /// @Prefix:<E>=@Category
  96. /// \endcode
  97. /// where @Query satisfies wildcard expression <E> in a given @Section.
  98. /// Returns zero if there is no exclusion entry corresponding to this
  99. /// expression.
  100. unsigned inSectionBlame(StringRef Section, StringRef Prefix, StringRef Query,
  101. StringRef Category = StringRef()) const;
  102. protected:
  103. // Implementations of the create*() functions that can also be used by derived
  104. // classes.
  105. bool createInternal(const std::vector<std::string> &Paths,
  106. vfs::FileSystem &VFS, std::string &Error);
  107. bool createInternal(const MemoryBuffer *MB, std::string &Error);
  108. SpecialCaseList() = default;
  109. SpecialCaseList(SpecialCaseList const &) = delete;
  110. SpecialCaseList &operator=(SpecialCaseList const &) = delete;
  111. /// Represents a set of regular expressions. Regular expressions which are
  112. /// "literal" (i.e. no regex metacharacters) are stored in Strings. The
  113. /// reason for doing so is efficiency; StringMap is much faster at matching
  114. /// literal strings than Regex.
  115. class Matcher {
  116. public:
  117. bool insert(std::string Regexp, unsigned LineNumber, std::string &REError);
  118. // Returns the line number in the source file that this query matches to.
  119. // Returns zero if no match is found.
  120. unsigned match(StringRef Query) const;
  121. private:
  122. StringMap<unsigned> Strings;
  123. TrigramIndex Trigrams;
  124. std::vector<std::pair<std::unique_ptr<Regex>, unsigned>> RegExes;
  125. };
  126. using SectionEntries = StringMap<StringMap<Matcher>>;
  127. struct Section {
  128. Section(std::unique_ptr<Matcher> M) : SectionMatcher(std::move(M)){};
  129. std::unique_ptr<Matcher> SectionMatcher;
  130. SectionEntries Entries;
  131. };
  132. std::vector<Section> Sections;
  133. /// Parses just-constructed SpecialCaseList entries from a memory buffer.
  134. bool parse(const MemoryBuffer *MB, StringMap<size_t> &SectionsMap,
  135. std::string &Error);
  136. // Helper method for derived classes to search by Prefix, Query, and Category
  137. // once they have already resolved a section entry.
  138. unsigned inSectionBlame(const SectionEntries &Entries, StringRef Prefix,
  139. StringRef Query, StringRef Category) const;
  140. };
  141. } // namespace llvm
  142. #endif // LLVM_SUPPORT_SPECIALCASELIST_H
  143. #ifdef __GNUC__
  144. #pragma GCC diagnostic pop
  145. #endif