mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-12 05:47:11 +03:00
Add automatic libFuzzer linking + fuzz test
This commit is contained in:
parent
4f5bd4a9bc
commit
800dc5a97f
3 changed files with 139 additions and 0 deletions
|
@ -45,6 +45,8 @@ public:
|
||||||
private:
|
private:
|
||||||
virtual void addSanitizers();
|
virtual void addSanitizers();
|
||||||
virtual void addASanLinkFlags();
|
virtual void addASanLinkFlags();
|
||||||
|
virtual void addFuzzLinkFlags();
|
||||||
|
virtual void addCppStdlibLinkFlags();
|
||||||
|
|
||||||
virtual void addUserSwitches();
|
virtual void addUserSwitches();
|
||||||
void addDefaultLibs();
|
void addDefaultLibs();
|
||||||
|
@ -260,11 +262,61 @@ void ArgsBuilder::addASanLinkFlags() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds all required link flags for -fsanitize=fuzzer when libFuzzer library is
|
||||||
|
// found.
|
||||||
|
void ArgsBuilder::addFuzzLinkFlags() {
|
||||||
|
std::string searchPaths[] = {
|
||||||
|
exe_path::prependLibDir("libFuzzer.a"),
|
||||||
|
exe_path::prependLibDir("libLLVMFuzzer.a"),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &filepath : searchPaths) {
|
||||||
|
if (llvm::sys::fs::exists(filepath)) {
|
||||||
|
args.push_back(filepath);
|
||||||
|
|
||||||
|
// libFuzzer requires the C++ std library, but only add the link flags
|
||||||
|
// when libFuzzer was found.
|
||||||
|
addCppStdlibLinkFlags();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgsBuilder::addCppStdlibLinkFlags() {
|
||||||
|
switch (global.params.targetTriple->getOS()) {
|
||||||
|
case llvm::Triple::Linux:
|
||||||
|
if (global.params.targetTriple->getEnvironment() == llvm::Triple::Android) {
|
||||||
|
args.push_back("-lc++");
|
||||||
|
} else {
|
||||||
|
args.push_back("-lstdc++");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case llvm::Triple::Solaris:
|
||||||
|
case llvm::Triple::NetBSD:
|
||||||
|
case llvm::Triple::OpenBSD:
|
||||||
|
case llvm::Triple::DragonFly:
|
||||||
|
args.push_back("-lstdc++");
|
||||||
|
break;
|
||||||
|
case llvm::Triple::Darwin:
|
||||||
|
case llvm::Triple::MacOSX:
|
||||||
|
case llvm::Triple::FreeBSD:
|
||||||
|
args.push_back("-lc++");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Don't know: do nothing so the user can step in
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ArgsBuilder::addSanitizers() {
|
void ArgsBuilder::addSanitizers() {
|
||||||
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
|
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
|
||||||
addASanLinkFlags();
|
addASanLinkFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts::isSanitizerEnabled(opts::FuzzSanitizer)) {
|
||||||
|
addFuzzLinkFlags();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: instead of this, we should link with our own sanitizer libraries
|
// TODO: instead of this, we should link with our own sanitizer libraries
|
||||||
// because LDC's LLVM version could be different from the system clang.
|
// because LDC's LLVM version could be different from the system clang.
|
||||||
if (opts::isSanitizerEnabled(opts::MemorySanitizer)) {
|
if (opts::isSanitizerEnabled(opts::MemorySanitizer)) {
|
||||||
|
|
49
tests/sanitizers/fuzz_asan.d
Normal file
49
tests/sanitizers/fuzz_asan.d
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Test Fuzz+ASan functionality
|
||||||
|
|
||||||
|
// REQUIRES: Fuzzer, ASan
|
||||||
|
|
||||||
|
// See https://github.com/ldc-developers/ldc/issues/2222 for -disable-fp-elim
|
||||||
|
// RUN: %ldc -g -fsanitize=address,fuzzer -disable-fp-elim %s -of=%t%exe
|
||||||
|
// RUN: not %t%exe 2>&1 | FileCheck %s
|
||||||
|
|
||||||
|
bool FuzzMe(ubyte* data, size_t dataSize)
|
||||||
|
{
|
||||||
|
return dataSize >= 6 &&
|
||||||
|
data[0] == 'F' &&
|
||||||
|
data[1] == 'U' &&
|
||||||
|
data[2] == 'Z' &&
|
||||||
|
data[3] == 'F' &&
|
||||||
|
data[4] == 'U' &&
|
||||||
|
data[5] == 'Z' &&
|
||||||
|
// CHECK: stack-buffer-overflow
|
||||||
|
// CHECK-NEXT: READ of size 1
|
||||||
|
// CHECK-NEXT: #0 {{.*}} in {{.*fuzz_asan6FuzzMe.*}} {{.*}}fuzz_asan.d:
|
||||||
|
// FIXME, debug line info is wrong (Github issue #2090). Once fixed, add [[@LINE+1]]
|
||||||
|
data[6] == 'Z'; // :‑<
|
||||||
|
}
|
||||||
|
|
||||||
|
extern (C) int LLVMFuzzerTestOneInput(const(ubyte*) data, size_t size)
|
||||||
|
{
|
||||||
|
// D runtime must be initialized, but only once.
|
||||||
|
static bool init = false;
|
||||||
|
if (!init)
|
||||||
|
{
|
||||||
|
import core.runtime : rt_init;
|
||||||
|
rt_init();
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubyte[6] stackdata;
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
for (auto i = 0; (i < size) && (i < stackdata.length); ++i)
|
||||||
|
stackdata[i] = data[i];
|
||||||
|
}
|
||||||
|
// CHECK-NEXT: #1 {{.*}} in LLVMFuzzerTestOneInput {{.*}}fuzz_asan.d:[[@LINE+1]]
|
||||||
|
FuzzMe(&stackdata[0], size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The test unit should start with "FUZFUZ"
|
||||||
|
// CHECK: FUZFUZ
|
38
tests/sanitizers/fuzz_basic.d
Normal file
38
tests/sanitizers/fuzz_basic.d
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Test basic fuzz test crash
|
||||||
|
|
||||||
|
// REQUIRES: Fuzzer
|
||||||
|
|
||||||
|
// RUN: %ldc -g -fsanitize=fuzzer %s -of=%t%exe
|
||||||
|
// RUN: not %t%exe 2>&1 | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: ERROR: libFuzzer: deadly signal
|
||||||
|
|
||||||
|
void FuzzMe(const(ubyte*) data, size_t size)
|
||||||
|
{
|
||||||
|
if ((size >= 6) && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z'
|
||||||
|
&& data[3] == 'L' && data[4] == 'D' && data[5] == 'C')
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern (C) int LLVMFuzzerTestOneInput(const(ubyte*) data, size_t size)
|
||||||
|
{
|
||||||
|
// D runtime must be initialized, but only once.
|
||||||
|
static bool init = false;
|
||||||
|
if (!init)
|
||||||
|
{
|
||||||
|
import core.runtime : rt_init;
|
||||||
|
|
||||||
|
rt_init();
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto a = new int; // Test that GC works
|
||||||
|
|
||||||
|
FuzzMe(data, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The test unit should start with "FUZLDC"
|
||||||
|
// CHECK: FUZLDC
|
Loading…
Add table
Add a link
Reference in a new issue