aboutsummaryrefslogtreecommitdiff
path: root/third_party
diff options
context:
space:
mode:
authorFabian Meumertzheim <meumertzheim@code-intelligence.com>2021-03-22 14:48:58 +0100
committerGitHub <noreply@github.com>2021-03-22 14:48:58 +0100
commit71ac55c6fc9d808bcc8a8e8d895f7f20141bec86 (patch)
treedfa557a023d1413799c24dbd1373d8c42c2ee8bb /third_party
parent20d72b43a58f5ffcb807245a854d7eb178c4b8b6 (diff)
downloadjazzer-api-71ac55c6fc9d808bcc8a8e8d895f7f20141bec86.tar.gz
Do not intercept JVM-internal C stdlib calls (#45)
* Replace uses of quick_exit and at_quick_exit quick_exit is not supported on macOS, but can easily replaced by a call to _Exit after running our cleanup manually. * Run buildifier --lint=fix -r . * Build libFuzzer from source Building libFuzzer from source is easy and has multiple advantages: * The clang distributed with XCode on macOS does not include libFuzzer. * Applying a small patch to libFuzzer will allow us to replace the --wrap linker feature, which is not supported on platforms other than Linux. * Replace -Wl,--wrap with a source code patch * Pin non-native rules_python * Print exit code on test failure * Do not intercept JVM-internal C stdlib calls The JVM frequently calls strcmp/memcmp/..., which fills up the table of recent compares with entries that are either duplicates of values already reported by the bytecode instrumentation or JDK-internal strings that are not relevant for fuzzing. This commit adds an ignorelist to the C stdlib interceptors that filters out calls from known JVM libraries. If the fuzz target has not yet loaded a native library, all such callbacks are ignored, which greatly improves fuzzer performance for string-heavy targets. E.g., JsonSanitizerDenylistFuzzer takes < 1 million runs now when it used to take over 3 million.
Diffstat (limited to 'third_party')
-rw-r--r--third_party/BUILD.bazel3
-rw-r--r--third_party/jni/BUILD.bazel2
-rw-r--r--third_party/libFuzzer-make-interceptors-configurable.patch109
-rw-r--r--third_party/libFuzzer-pass-death-callback-to-jazzer.patch28
-rw-r--r--third_party/libFuzzer.BUILD21
5 files changed, 163 insertions, 0 deletions
diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel
index fd65eb9b..b391ce54 100644
--- a/third_party/BUILD.bazel
+++ b/third_party/BUILD.bazel
@@ -2,5 +2,8 @@ exports_files([
"gflags-use-double-dash-args.patch",
"jacoco-make-probe-inserter-subclassable.patch",
"jacoco_internal.BUILD",
+ "libFuzzer-make-interceptors-configurable.patch",
+ "libFuzzer-pass-death-callback-to-jazzer.patch",
+ "libFuzzer.BUILD",
"libjpeg_turbo.BUILD",
])
diff --git a/third_party/jni/BUILD.bazel b/third_party/jni/BUILD.bazel
index 4d5fdd00..cda76ef0 100644
--- a/third_party/jni/BUILD.bazel
+++ b/third_party/jni/BUILD.bazel
@@ -1,3 +1,5 @@
+load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library")
+
cc_library(
name = "jni",
visibility = ["//visibility:public"],
diff --git a/third_party/libFuzzer-make-interceptors-configurable.patch b/third_party/libFuzzer-make-interceptors-configurable.patch
new file mode 100644
index 00000000..9420c4aa
--- /dev/null
+++ b/third_party/libFuzzer-make-interceptors-configurable.patch
@@ -0,0 +1,109 @@
+diff --git compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
+index b87798603fda..10e34ee86cce 100644
+--- compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
++++ compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
+@@ -147,11 +147,18 @@ DEFINE_REAL(char *, strstr, const char *, const char *)
+ DEFINE_REAL(char *, strcasestr, const char *, const char *)
+ DEFINE_REAL(void *, memmem, const void *, size_t, const void *, size_t)
+
++extern "C" __attribute__((weak)) bool
++__sanitizer_weak_is_relevant_pc(void * caller_pc) {
++ return false;
++}
++
+ ATTRIBUTE_INTERFACE int bcmp(const char *s1, const char *s2, size_t n) {
+ if (!FuzzerInited)
+ return internal_memcmp(s1, s2, n);
+ int result = REAL(bcmp)(s1, s2, n);
+- __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_memcmp(caller_pc, s1, s2, n, result);
+ return result;
+ }
+
+@@ -159,7 +166,9 @@ ATTRIBUTE_INTERFACE int memcmp(const void *s1, const void *s2, size_t n) {
+ if (!FuzzerInited)
+ return internal_memcmp(s1, s2, n);
+ int result = REAL(memcmp)(s1, s2, n);
+- __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_memcmp(caller_pc, s1, s2, n, result);
+ return result;
+ }
+
+@@ -167,7 +176,9 @@ ATTRIBUTE_INTERFACE int strncmp(const char *s1, const char *s2, size_t n) {
+ if (!FuzzerInited)
+ return internal_strncmp(s1, s2, n);
+ int result = REAL(strncmp)(s1, s2, n);
+- __sanitizer_weak_hook_strncmp(GET_CALLER_PC(), s1, s2, n, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_strncmp(caller_pc, s1, s2, n, result);
+ return result;
+ }
+
+@@ -175,21 +186,27 @@ ATTRIBUTE_INTERFACE int strcmp(const char *s1, const char *s2) {
+ if (!FuzzerInited)
+ return internal_strcmp(s1, s2);
+ int result = REAL(strcmp)(s1, s2);
+- __sanitizer_weak_hook_strcmp(GET_CALLER_PC(), s1, s2, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_strcmp(caller_pc, s1, s2, result);
+ return result;
+ }
+
+ ATTRIBUTE_INTERFACE int strncasecmp(const char *s1, const char *s2, size_t n) {
+ ensureFuzzerInited();
+ int result = REAL(strncasecmp)(s1, s2, n);
+- __sanitizer_weak_hook_strncasecmp(GET_CALLER_PC(), s1, s2, n, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_strncasecmp(caller_pc, s1, s2, n, result);
+ return result;
+ }
+
+ ATTRIBUTE_INTERFACE int strcasecmp(const char *s1, const char *s2) {
+ ensureFuzzerInited();
+ int result = REAL(strcasecmp)(s1, s2);
+- __sanitizer_weak_hook_strcasecmp(GET_CALLER_PC(), s1, s2, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_strcasecmp(caller_pc, s1, s2, result);
+ return result;
+ }
+
+@@ -197,14 +214,18 @@ ATTRIBUTE_INTERFACE char *strstr(const char *s1, const char *s2) {
+ if (!FuzzerInited)
+ return internal_strstr(s1, s2);
+ char *result = REAL(strstr)(s1, s2);
+- __sanitizer_weak_hook_strstr(GET_CALLER_PC(), s1, s2, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_strstr(caller_pc, s1, s2, result);
+ return result;
+ }
+
+ ATTRIBUTE_INTERFACE char *strcasestr(const char *s1, const char *s2) {
+ ensureFuzzerInited();
+ char *result = REAL(strcasestr)(s1, s2);
+- __sanitizer_weak_hook_strcasestr(GET_CALLER_PC(), s1, s2, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_strcasestr(caller_pc, s1, s2, result);
+ return result;
+ }
+
+@@ -212,7 +233,9 @@ ATTRIBUTE_INTERFACE
+ void *memmem(const void *s1, size_t len1, const void *s2, size_t len2) {
+ ensureFuzzerInited();
+ void *result = REAL(memmem)(s1, len1, s2, len2);
+- __sanitizer_weak_hook_memmem(GET_CALLER_PC(), s1, len1, s2, len2, result);
++ void *caller_pc = GET_CALLER_PC();
++ if (__sanitizer_weak_is_relevant_pc(caller_pc))
++ __sanitizer_weak_hook_memmem(caller_pc, s1, len1, s2, len2, result);
+ return result;
+ }
+
diff --git a/third_party/libFuzzer-pass-death-callback-to-jazzer.patch b/third_party/libFuzzer-pass-death-callback-to-jazzer.patch
new file mode 100644
index 00000000..3fb9fbb0
--- /dev/null
+++ b/third_party/libFuzzer-pass-death-callback-to-jazzer.patch
@@ -0,0 +1,28 @@
+diff --git compiler-rt/lib/fuzzer/FuzzerExtFunctions.def compiler-rt/lib/fuzzer/FuzzerExtFunctions.def
+index 51edf8444e94..e31f0040268b 100644
+--- compiler-rt/lib/fuzzer/FuzzerExtFunctions.def
++++ compiler-rt/lib/fuzzer/FuzzerExtFunctions.def
+@@ -42,7 +42,7 @@ EXT_FUNC(__sanitizer_symbolize_pc, void,
+ EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int,
+ (void *pc, char *module_path,
+ size_t module_path_len,void **pc_offset), false);
+-EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true);
++EXT_FUNC(__jazzer_set_death_callback, void, (void (*)(void)), true);
+ EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false);
+ EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false);
+ EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false);
+diff --git compiler-rt/lib/fuzzer/FuzzerLoop.cpp compiler-rt/lib/fuzzer/FuzzerLoop.cpp
+index 149742b4c2fe..7b361423cc32 100644
+--- compiler-rt/lib/fuzzer/FuzzerLoop.cpp
++++ compiler-rt/lib/fuzzer/FuzzerLoop.cpp
+@@ -138,8 +138,8 @@ void Fuzzer::HandleMalloc(size_t Size) {
+ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
+ FuzzingOptions Options)
+ : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
+- if (EF->__sanitizer_set_death_callback)
+- EF->__sanitizer_set_death_callback(StaticDeathCallback);
++ if (EF->__jazzer_set_death_callback)
++ EF->__jazzer_set_death_callback(StaticDeathCallback);
+ assert(!F);
+ F = this;
+ TPC.ResetMaps();
diff --git a/third_party/libFuzzer.BUILD b/third_party/libFuzzer.BUILD
new file mode 100644
index 00000000..4bd464a4
--- /dev/null
+++ b/third_party/libFuzzer.BUILD
@@ -0,0 +1,21 @@
+# Based on https://github.com/llvm/llvm-project/blob/llvmorg-11.1.0/compiler-rt/lib/fuzzer/build.sh
+LIB_FUZZER_PATH = "compiler-rt/lib/fuzzer"
+
+cc_library(
+ name = "libFuzzer",
+ srcs = glob([
+ LIB_FUZZER_PATH + "/*.cpp",
+ ]),
+ hdrs = glob([
+ LIB_FUZZER_PATH + "/*.h",
+ LIB_FUZZER_PATH + "/*.def",
+ ]),
+ copts = [
+ "-g",
+ "-O2",
+ "-fno-omit-frame-pointer",
+ "-std=c++11",
+ ],
+ alwayslink = True,
+ visibility = ["//visibility:public"],
+)