mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
0b4abdf3cc
Summary: Sanitizer blacklist entries currently apply to all sanitizers--there is no way to specify that an entry should only apply to a specific sanitizer. This is important for Control Flow Integrity since there are several different CFI modes that can be enabled at once. For maximum security, CFI blacklist entries should be scoped to only the specific CFI mode(s) that entry applies to. Adding section headers to SpecialCaseLists allows users to specify more information about list entries, like sanitizer names or other metadata, like so: [section1] fun:*fun1* [section2|section3] fun:*fun23* The section headers are regular expressions. For backwards compatbility, blacklist entries entered before a section header are put into the '[*]' section so that blacklists without sections retain the same behavior. SpecialCaseList has been modified to also accept a section name when matching against the blacklist. It has also been modified so the follow-up change to clang can define a derived class that allows matching sections by SectionMask instead of by string. Reviewers: pcc, kcc, eugenis, vsk Reviewed By: eugenis, vsk Subscribers: vitalybuka, llvm-commits Differential Revision: https://reviews.llvm.org/D37924 llvm-svn: 314170
221 lines
9.1 KiB
C++
221 lines
9.1 KiB
C++
//===- SpecialCaseListTest.cpp - Unit tests for SpecialCaseList -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/SpecialCaseList.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class SpecialCaseListTest : public ::testing::Test {
|
|
protected:
|
|
std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List,
|
|
std::string &Error) {
|
|
std::unique_ptr<MemoryBuffer> MB = MemoryBuffer::getMemBuffer(List);
|
|
return SpecialCaseList::create(MB.get(), Error);
|
|
}
|
|
|
|
std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List) {
|
|
std::string Error;
|
|
auto SCL = makeSpecialCaseList(List, Error);
|
|
assert(SCL);
|
|
assert(Error == "");
|
|
return SCL;
|
|
}
|
|
|
|
std::string makeSpecialCaseListFile(StringRef Contents) {
|
|
int FD;
|
|
SmallString<64> Path;
|
|
sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path);
|
|
raw_fd_ostream OF(FD, true, true);
|
|
OF << Contents;
|
|
OF.close();
|
|
return Path.str();
|
|
}
|
|
};
|
|
|
|
TEST_F(SpecialCaseListTest, Basic) {
|
|
std::unique_ptr<SpecialCaseList> SCL =
|
|
makeSpecialCaseList("# This is a comment.\n"
|
|
"\n"
|
|
"src:hello\n"
|
|
"src:bye\n"
|
|
"src:hi=category\n"
|
|
"src:z*=category\n");
|
|
EXPECT_TRUE(SCL->inSection("", "src", "hello"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "bye"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "hi", "category"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "zzzz", "category"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "hi"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "hello"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "hello", "category"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, SectionRegexErrorHandling) {
|
|
std::string Error;
|
|
EXPECT_EQ(makeSpecialCaseList("[address", Error), nullptr);
|
|
EXPECT_TRUE(((StringRef)Error).startswith("malformed section header "));
|
|
|
|
EXPECT_EQ(makeSpecialCaseList("[[]", Error), nullptr);
|
|
EXPECT_TRUE(((StringRef)Error).startswith("malformed regex for section [: "));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, Section) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:global\n"
|
|
"[sect1|sect2]\n"
|
|
"src:test1\n"
|
|
"[sect3*]\n"
|
|
"src:test2\n");
|
|
EXPECT_TRUE(SCL->inSection("arbitrary", "src", "global"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "global"));
|
|
EXPECT_TRUE(SCL->inSection("sect1", "src", "test1"));
|
|
EXPECT_FALSE(SCL->inSection("sect1-arbitrary", "src", "test1"));
|
|
EXPECT_FALSE(SCL->inSection("sect", "src", "test1"));
|
|
EXPECT_FALSE(SCL->inSection("sect1", "src", "test2"));
|
|
EXPECT_TRUE(SCL->inSection("sect2", "src", "test1"));
|
|
EXPECT_TRUE(SCL->inSection("sect3", "src", "test2"));
|
|
EXPECT_TRUE(SCL->inSection("sect3-arbitrary", "src", "test2"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "test1"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "test2"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, GlobalInit) {
|
|
std::unique_ptr<SpecialCaseList> SCL =
|
|
makeSpecialCaseList("global:foo=init\n");
|
|
EXPECT_FALSE(SCL->inSection("", "global", "foo"));
|
|
EXPECT_FALSE(SCL->inSection("", "global", "bar"));
|
|
EXPECT_TRUE(SCL->inSection("", "global", "foo", "init"));
|
|
EXPECT_FALSE(SCL->inSection("", "global", "bar", "init"));
|
|
|
|
SCL = makeSpecialCaseList("type:t2=init\n");
|
|
EXPECT_FALSE(SCL->inSection("", "type", "t1"));
|
|
EXPECT_FALSE(SCL->inSection("", "type", "t2"));
|
|
EXPECT_FALSE(SCL->inSection("", "type", "t1", "init"));
|
|
EXPECT_TRUE(SCL->inSection("", "type", "t2", "init"));
|
|
|
|
SCL = makeSpecialCaseList("src:hello=init\n");
|
|
EXPECT_FALSE(SCL->inSection("", "src", "hello"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "bye"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "hello", "init"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "bye", "init"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, Substring) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:hello\n"
|
|
"fun:foo\n"
|
|
"global:bar\n");
|
|
EXPECT_FALSE(SCL->inSection("", "src", "othello"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "tomfoolery"));
|
|
EXPECT_FALSE(SCL->inSection("", "global", "bartender"));
|
|
|
|
SCL = makeSpecialCaseList("fun:*foo*\n");
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "tomfoolery"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "foobar"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
|
|
std::string Error;
|
|
EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error));
|
|
EXPECT_EQ("malformed line 1: 'badline'", Error);
|
|
EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error));
|
|
EXPECT_EQ("malformed regex in line 1: 'bad[a-': invalid character range",
|
|
Error);
|
|
EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n"
|
|
"fun:fun(a\n",
|
|
Error));
|
|
EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced",
|
|
Error);
|
|
std::vector<std::string> Files(1, "unexisting");
|
|
EXPECT_EQ(nullptr, SpecialCaseList::create(Files, Error));
|
|
EXPECT_EQ(0U, Error.find("can't open file 'unexisting':"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("");
|
|
EXPECT_FALSE(SCL->inSection("", "foo", "bar"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, MultipleBlacklists) {
|
|
std::vector<std::string> Files;
|
|
Files.push_back(makeSpecialCaseListFile("src:bar\n"
|
|
"src:*foo*\n"
|
|
"src:ban=init\n"));
|
|
Files.push_back(makeSpecialCaseListFile("src:baz\n"
|
|
"src:*fog*\n"));
|
|
auto SCL = SpecialCaseList::createOrDie(Files);
|
|
EXPECT_TRUE(SCL->inSection("", "src", "bar"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "baz"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "ban"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "ban", "init"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "tomfoolery"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "tomfoglery"));
|
|
for (auto &Path : Files)
|
|
sys::fs::remove(Path);
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, NoTrigramsInRules) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:b.r\n"
|
|
"fun:za*az\n");
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "bar"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "baz"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "zakaz"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "zaraza"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, NoTrigramsInARule) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*bar*\n"
|
|
"fun:za*az\n");
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "abara"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "bor"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "zakaz"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "zaraza"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, RepetitiveRule) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*bar*bar*bar*bar*\n"
|
|
"fun:bar*\n");
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "bara"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "abara"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "barbarbarbar"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "abarbarbarbar"));
|
|
EXPECT_FALSE(SCL->inSection("", "fun", "abarbarbar"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, SpecialSymbolRule) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:*c\\+\\+abi*\n");
|
|
EXPECT_TRUE(SCL->inSection("", "src", "c++abi"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, PopularTrigram) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*aaaaaa*\n"
|
|
"fun:*aaaaa*\n"
|
|
"fun:*aaaa*\n"
|
|
"fun:*aaa*\n");
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "aaa"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "aaaa"));
|
|
EXPECT_TRUE(SCL->inSection("", "fun", "aaaabbbaaa"));
|
|
}
|
|
|
|
TEST_F(SpecialCaseListTest, EscapedSymbols) {
|
|
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:*c\\+\\+abi*\n"
|
|
"src:*hello\\\\world*\n");
|
|
EXPECT_TRUE(SCL->inSection("", "src", "dir/c++abi"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "dir/c\\+\\+abi"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "C:\\hello\\world"));
|
|
EXPECT_TRUE(SCL->inSection("", "src", "hello\\world"));
|
|
EXPECT_FALSE(SCL->inSection("", "src", "hello\\\\world"));
|
|
}
|
|
|
|
}
|