1//===-- sanitizer_suppressions_test.cpp -----------------------------------===//
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 file is a part of ThreadSanitizer/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12#include "sanitizer_common/sanitizer_suppressions.h"
13#include "gtest/gtest.h"
14
15#include <string.h>
16
17namespace __sanitizer {
18
19static bool MyMatch(const char *templ, const char *func) {
20  char tmp[1024];
21  snprintf(tmp, sizeof(tmp), "%s", templ);
22  return TemplateMatch(tmp, func);
23}
24
25TEST(Suppressions, Match) {
26  EXPECT_TRUE(MyMatch("foobar$", "foobar"));
27
28  EXPECT_TRUE(MyMatch("foobar", "foobar"));
29  EXPECT_TRUE(MyMatch("*foobar*", "foobar"));
30  EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix"));
31  EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix"));
32  EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar"));
33  EXPECT_TRUE(MyMatch("foo*bar", "foobar"));
34  EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz"));
35  EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz"));
36  EXPECT_TRUE(MyMatch("^foobar", "foobar"));
37  EXPECT_TRUE(MyMatch("^foobar", "foobar_postfix"));
38  EXPECT_TRUE(MyMatch("^*foobar", "foobar"));
39  EXPECT_TRUE(MyMatch("^*foobar", "prefix_foobar"));
40  EXPECT_TRUE(MyMatch("foobar$", "foobar"));
41  EXPECT_TRUE(MyMatch("foobar$", "prefix_foobar"));
42  EXPECT_TRUE(MyMatch("*foobar*$", "foobar"));
43  EXPECT_TRUE(MyMatch("*foobar*$", "foobar_postfix"));
44  EXPECT_TRUE(MyMatch("^foobar$", "foobar"));
45
46  EXPECT_FALSE(MyMatch("foo", "baz"));
47  EXPECT_FALSE(MyMatch("foobarbaz", "foobar"));
48  EXPECT_FALSE(MyMatch("foobarbaz", "barbaz"));
49  EXPECT_FALSE(MyMatch("foo*bar", "foobaz"));
50  EXPECT_FALSE(MyMatch("foo*bar", "foo_baz"));
51  EXPECT_FALSE(MyMatch("^foobar", "prefix_foobar"));
52  EXPECT_FALSE(MyMatch("foobar$", "foobar_postfix"));
53  EXPECT_FALSE(MyMatch("^foobar$", "prefix_foobar"));
54  EXPECT_FALSE(MyMatch("^foobar$", "foobar_postfix"));
55  EXPECT_FALSE(MyMatch("foo^bar", "foobar"));
56  EXPECT_FALSE(MyMatch("foo$bar", "foobar"));
57  EXPECT_FALSE(MyMatch("foo$^bar", "foobar"));
58}
59
60static const char *kTestSuppressionTypes[] = {"race", "thread", "mutex",
61                                              "signal"};
62
63class SuppressionContextTest : public ::testing::Test {
64 public:
65  SuppressionContextTest()
66      : ctx_(kTestSuppressionTypes, ARRAY_SIZE(kTestSuppressionTypes)) {}
67
68 protected:
69  SuppressionContext ctx_;
70
71  void CheckSuppressions(unsigned count, std::vector<const char *> types,
72                         std::vector<const char *> templs) const {
73    EXPECT_EQ(count, ctx_.SuppressionCount());
74    for (unsigned i = 0; i < count; i++) {
75      const Suppression *s = ctx_.SuppressionAt(i);
76      EXPECT_STREQ(types[i], s->type);
77      EXPECT_STREQ(templs[i], s->templ);
78    }
79  }
80};
81
82TEST_F(SuppressionContextTest, Parse) {
83  ctx_.Parse(
84      "race:foo\n"
85      " \trace:bar\n"
86      "race:baz\t \n"
87      "# a comment\n"
88      "race:quz\n");
89  CheckSuppressions(4, {"race", "race", "race", "race"},
90                    {"foo", "bar", "baz", "quz"});
91}
92
93TEST_F(SuppressionContextTest, Parse2) {
94  ctx_.Parse(
95      "  \t# first line comment\n"
96      " \trace:bar \t\n"
97      "race:baz* *baz\n"
98      "# a comment\n"
99      "# last line comment\n");
100  CheckSuppressions(2, {"race", "race"}, {"bar", "baz* *baz"});
101}
102
103TEST_F(SuppressionContextTest, Parse3) {
104  ctx_.Parse(
105      "# last suppression w/o line-feed\n"
106      "race:foo\n"
107      "race:bar\r\n"
108      "race:baz");
109  CheckSuppressions(3, {"race", "race", "race"}, {"foo", "bar", "baz"});
110}
111
112TEST_F(SuppressionContextTest, ParseType) {
113  ctx_.Parse(
114      "race:foo\n"
115      "thread:bar\n"
116      "mutex:baz\n"
117      "signal:quz\n");
118  CheckSuppressions(4, {"race", "thread", "mutex", "signal"},
119                    {"foo", "bar", "baz", "quz"});
120}
121
122TEST_F(SuppressionContextTest, HasSuppressionType) {
123  ctx_.Parse(
124    "race:foo\n"
125    "thread:bar\n");
126  EXPECT_TRUE(ctx_.HasSuppressionType("race"));
127  EXPECT_TRUE(ctx_.HasSuppressionType("thread"));
128  EXPECT_FALSE(ctx_.HasSuppressionType("mutex"));
129  EXPECT_FALSE(ctx_.HasSuppressionType("signal"));
130}
131
132TEST_F(SuppressionContextTest, RegressionTestForBufferOverflowInSuppressions) {
133  EXPECT_DEATH(ctx_.Parse("race"), "failed to parse suppressions");
134  EXPECT_DEATH(ctx_.Parse("foo"), "failed to parse suppressions");
135}
136
137
138}  // namespace __sanitizer
139