summaryrefslogtreecommitdiff
path: root/tools/gwp_asan
diff options
context:
space:
mode:
authorMitch Phillips <mitchphillips@outlook.com>2019-08-27 18:28:07 +0000
committerMitch Phillips <mitchphillips@outlook.com>2019-08-27 18:28:07 +0000
commit67188fd9f6cc3497484c321bfc78776ae612aba2 (patch)
treed33f6b56d7a9f427210eca7fdaf9bd94f9e7bff6 /tools/gwp_asan
parentf23db13d0351b6f90fc22c690fe07948a6cb5f2a (diff)
downloadcompiler-rt-67188fd9f6cc3497484c321bfc78776ae612aba2.tar.gz
Add GWP-ASan fuzz target to compiler-rt/tools.
Summary: @eugenis to approve addition of //compiler-rt/tools. @pree-jackie please confirm that this WFY. D66494 introduced the GWP-ASan stack_trace_compressor_fuzzer. Building fuzz targets in compiler-rt is a new affair, and has some challenges: - If the host compiler doesn't have compiler-rt, the -fsanitize=fuzzer may not be able to link against `libclang_rt.fuzzer*`. - Things in compiler-rt generally aren't built when you want to build with sanitizers using `-DLLVM_USE_SANITIZER`. This tricky to work around, so we create the new tools directory so that we can build fuzz targets with sanitizers. This has the added bonus of fixing the problem above as well, as we can now just guard the fuzz target build to only be done with `-DLLVM_USE_SANITIZE_COVERAGE=On`. Reviewers: eugenis, pree-jackie Reviewed By: eugenis, pree-jackie Subscribers: dberris, mgorny, #sanitizers, llvm-commits, eugenis, pree-jackie, lebedev.ri, vitalybuka, morehouse Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D66776 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@370094 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/gwp_asan')
-rw-r--r--tools/gwp_asan/CMakeLists.txt20
-rw-r--r--tools/gwp_asan/stack_trace_compressor_fuzzer.cpp49
2 files changed, 69 insertions, 0 deletions
diff --git a/tools/gwp_asan/CMakeLists.txt b/tools/gwp_asan/CMakeLists.txt
new file mode 100644
index 000000000..b0f9f0cf9
--- /dev/null
+++ b/tools/gwp_asan/CMakeLists.txt
@@ -0,0 +1,20 @@
+# Build the stack trace compressor fuzzer. This will require Clang >= 6.0.0, as
+# -fsanitize=fuzzer-no-link was not a valid command line flag prior to this.
+if (LLVM_USE_SANITIZE_COVERAGE)
+ add_executable(stack_trace_compressor_fuzzer
+ ../../lib/gwp_asan/stack_trace_compressor.cpp
+ ../../lib/gwp_asan/stack_trace_compressor.h
+ stack_trace_compressor_fuzzer.cpp)
+ set_target_properties(
+ stack_trace_compressor_fuzzer PROPERTIES FOLDER "Fuzzers")
+ target_compile_options(
+ stack_trace_compressor_fuzzer PRIVATE -fsanitize=fuzzer-no-link)
+ set_target_properties(
+ stack_trace_compressor_fuzzer PROPERTIES LINK_FLAGS -fsanitize=fuzzer)
+ target_include_directories(
+ stack_trace_compressor_fuzzer PRIVATE ../../lib/)
+
+ if (TARGET gwp_asan)
+ add_dependencies(gwp_asan stack_trace_compressor_fuzzer)
+ endif()
+endif()
diff --git a/tools/gwp_asan/stack_trace_compressor_fuzzer.cpp b/tools/gwp_asan/stack_trace_compressor_fuzzer.cpp
new file mode 100644
index 000000000..aa57fdaff
--- /dev/null
+++ b/tools/gwp_asan/stack_trace_compressor_fuzzer.cpp
@@ -0,0 +1,49 @@
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <vector>
+
+#include "gwp_asan/stack_trace_compressor.h"
+
+constexpr size_t kBytesForLargestVarInt = (sizeof(uintptr_t) * 8) / 7 + 1;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ size_t BufferSize = kBytesForLargestVarInt * Size / sizeof(uintptr_t);
+ std::vector<uint8_t> Buffer(BufferSize);
+ std::vector<uint8_t> Buffer2(BufferSize);
+
+ // Unpack the fuzz bytes.
+ gwp_asan::compression::unpack(Data, Size,
+ reinterpret_cast<uintptr_t *>(Buffer2.data()),
+ BufferSize / sizeof(uintptr_t));
+
+ // Pack the fuzz bytes.
+ size_t BytesWritten = gwp_asan::compression::pack(
+ reinterpret_cast<const uintptr_t *>(Data), Size / sizeof(uintptr_t),
+ Buffer.data(), BufferSize);
+
+ // Unpack the compressed buffer.
+ size_t DecodedElements = gwp_asan::compression::unpack(
+ Buffer.data(), BytesWritten,
+ reinterpret_cast<uintptr_t *>(Buffer2.data()),
+ BufferSize / sizeof(uintptr_t));
+
+ // Ensure that every element was encoded and decoded properly.
+ if (DecodedElements != Size / sizeof(uintptr_t))
+ abort();
+
+ // Ensure that the compression and uncompression resulted in the same trace.
+ const uintptr_t *FuzzPtrs = reinterpret_cast<const uintptr_t *>(Data);
+ const uintptr_t *DecodedPtrs =
+ reinterpret_cast<const uintptr_t *>(Buffer2.data());
+ for (size_t i = 0; i < Size / sizeof(uintptr_t); ++i) {
+ if (FuzzPtrs[i] != DecodedPtrs[i]) {
+ fprintf(stderr, "FuzzPtrs[%zu] != DecodedPtrs[%zu] (0x%zx vs. 0x%zx)", i,
+ i, FuzzPtrs[i], DecodedPtrs[i]);
+ abort();
+ }
+ }
+
+ return 0;
+}