dokyungs updated this revision to Diff 277530.
dokyungs added a comment.

Fixed a few LINT warnings by defining some macros that resemble the ones used 
in other sanitizer interception code.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83494/new/

https://reviews.llvm.org/D83494

Files:
  clang/include/clang/Driver/SanitizerArgs.h
  clang/lib/Driver/SanitizerArgs.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  compiler-rt/lib/fuzzer/CMakeLists.txt
  compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
  compiler-rt/test/fuzzer/no-asan-memcmp.test
  compiler-rt/test/fuzzer/no-asan-strcmp.test
  compiler-rt/test/fuzzer/no-asan-strncmp.test
  compiler-rt/test/fuzzer/no-asan-strstr.test

Index: compiler-rt/test/fuzzer/no-asan-strstr.test
===================================================================
--- /dev/null
+++ compiler-rt/test/fuzzer/no-asan-strstr.test
@@ -0,0 +1,5 @@
+UNSUPPORTED: freebsd
+RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-strstr %S/StrstrTest.cpp -o %t-StrstrTest
+RUN: not %run %t-StrstrTest               -seed=1 -runs=2000000   2>&1 | FileCheck %s
+CHECK: BINGO
+
Index: compiler-rt/test/fuzzer/no-asan-strncmp.test
===================================================================
--- /dev/null
+++ compiler-rt/test/fuzzer/no-asan-strncmp.test
@@ -0,0 +1,4 @@
+UNSUPPORTED: freebsd
+RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-strncmp  %S/StrncmpTest.cpp -o %t-StrncmpTest
+RUN: not %run %t-StrncmpTest              -seed=2 -runs=10000000   2>&1 | FileCheck %s
+CHECK: BINGO
Index: compiler-rt/test/fuzzer/no-asan-strcmp.test
===================================================================
--- /dev/null
+++ compiler-rt/test/fuzzer/no-asan-strcmp.test
@@ -0,0 +1,5 @@
+UNSUPPORTED: freebsd
+RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-strcmp %S/StrcmpTest.cpp -o %t-StrcmpTest
+RUN: not %run %t-StrcmpTest               -seed=1 -runs=2000000   2>&1 | FileCheck %s
+CHECK: BINGO
+
Index: compiler-rt/test/fuzzer/no-asan-memcmp.test
===================================================================
--- /dev/null
+++ compiler-rt/test/fuzzer/no-asan-memcmp.test
@@ -0,0 +1,4 @@
+UNSUPPORTED: freebsd
+RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-memcmp %S/MemcmpTest.cpp -o %t-MemcmpTest
+RUN: not %run %t-MemcmpTest               -seed=1 -runs=10000000   2>&1 | FileCheck %s
+CHECK: BINGO
Index: compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
===================================================================
--- /dev/null
+++ compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
@@ -0,0 +1,161 @@
+//===-- FuzzerInterceptors.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Intercept certain libc functions to aid fuzzing.
+// Linked only when other RTs that define their own interceptors are not linked.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerBuiltins.h"
+
+#if LIBFUZZER_LINUX
+
+#define PTR_TO_REAL(x) real_##x
+#define REAL(x) __interception::PTR_TO_REAL(x)
+#define FUNC_TYPE(x) x##_type
+#define DEFINE_REAL(ret_type, func, ...)                                       \
+  typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__);                            \
+  namespace __interception {                                                   \
+  FUNC_TYPE(func) PTR_TO_REAL(func);                                           \
+  }
+
+typedef unsigned long uptr;
+
+#include <dlfcn.h> // for dlsym()
+
+static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
+  void *addr = dlsym(RTLD_NEXT, name);
+  if (!addr) {
+    // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is
+    // later in the library search order than the DSO that we are trying to
+    // intercept, which means that we cannot intercept this function. We still
+    // want the address of the real definition, though, so look it up using
+    // RTLD_DEFAULT.
+    addr = dlsym(RTLD_DEFAULT, name);
+
+    // In case `name' is not loaded, dlsym ends up finding the actual wrapper.
+    // We don't want to intercept the wrapper and have it point to itself.
+    if ((uptr)addr == wrapper_addr)
+      addr = nullptr;
+  }
+  return addr;
+}
+
+extern "C" {
+
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_memcmp(void *, const void *, const void *, size_t,
+                                  int);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_strncmp(void *, const char *, const char *, size_t,
+                                   int);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_strcmp(void *, const char *, const char *, int);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_strncasecmp(void *, const char *, const char *,
+                                       size_t, int);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_strcasecmp(void *, const char *, const char *, int);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_strstr(void *, const char *, const char *, char *);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_strcasestr(void *, const char *, const char *,
+                                      char *);
+// NOLINTNEXTLINE
+void __sanitizer_weak_hook_memmem(void *, const void *, size_t, const void *,
+                                  size_t, void *);
+
+DEFINE_REAL(int, memcmp, const void *, const void *, size_t)
+DEFINE_REAL(int, strncmp, const char *, const char *, size_t)
+DEFINE_REAL(int, strcmp, const char *, const char *)
+DEFINE_REAL(int, strncasecmp, const char *, const char *, size_t)
+DEFINE_REAL(int, strcasecmp, const char *, const char *)
+DEFINE_REAL(char *, strstr, char *, const char *)
+DEFINE_REAL(char *, strcasestr, char *, const char *)
+DEFINE_REAL(void *, memmem, const void *, size_t, const void *, size_t)
+
+ATTRIBUTE_INTERFACE int memcmp(const void *s1, const void *s2, size_t n) {
+  int result = REAL(memcmp)(s1, s2, n);
+  __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result);
+
+  return result;
+}
+
+ATTRIBUTE_INTERFACE int strncmp(const char *s1, const char *s2, size_t n) {
+  int result = REAL(strncmp)(s1, s2, n);
+  __sanitizer_weak_hook_strncmp(GET_CALLER_PC(), s1, s2, n, result);
+
+  return result;
+}
+
+ATTRIBUTE_INTERFACE int strcmp(const char *s1, const char *s2) {
+  int result = REAL(strcmp)(s1, s2);
+  __sanitizer_weak_hook_strcmp(GET_CALLER_PC(), s1, s2, result);
+
+  return result;
+}
+
+ATTRIBUTE_INTERFACE int strncasecmp(const char *s1, const char *s2, size_t n) {
+  int result = REAL(strncasecmp)(s1, s2, n);
+  __sanitizer_weak_hook_strncasecmp(GET_CALLER_PC(), s1, s2, n, result);
+
+  return result;
+}
+
+ATTRIBUTE_INTERFACE
+int strcasecmp(const char *s1, const char *s2) {
+  int result = REAL(strcasecmp)(s1, s2);
+  __sanitizer_weak_hook_strcasecmp(GET_CALLER_PC(), s1, s2, result);
+
+  return result;
+}
+
+extern "C++" ATTRIBUTE_INTERFACE char *strstr(char *s1, const char *s2) {
+  char *result = REAL(strstr)(s1, s2);
+  __sanitizer_weak_hook_strstr(GET_CALLER_PC(), s1, s2, result);
+
+  return result;
+}
+
+extern "C++" ATTRIBUTE_INTERFACE char *strcasestr(char *s1, const char *s2) {
+  char *result = REAL(strcasestr)(s1, s2);
+  __sanitizer_weak_hook_strcasestr(GET_CALLER_PC(), s1, s2, result);
+
+  return result;
+}
+
+ATTRIBUTE_INTERFACE
+void *memmem(const void *s1, size_t len1, const void *s2, size_t len2) {
+  void *result = REAL(memmem)(s1, len1, s2, len2);
+  __sanitizer_weak_hook_memmem(GET_CALLER_PC(), s1, len1, s2, len2, result);
+
+  return result;
+}
+
+static void __fuzzer_init() {
+  REAL(memcmp) =
+      reinterpret_cast<memcmp_type>(GetFuncAddr("memcmp", (uptr)&memcmp));
+  REAL(strncmp) =
+      reinterpret_cast<strncmp_type>(GetFuncAddr("strncmp", (uptr)&strncmp));
+  REAL(strcmp) =
+      reinterpret_cast<strcmp_type>(GetFuncAddr("strcmp", (uptr)&strcmp));
+  REAL(strncasecmp) = reinterpret_cast<strncasecmp_type>(
+      GetFuncAddr("strncasecmp", (uptr)&strncasecmp));
+  REAL(strcasecmp) = reinterpret_cast<strcasecmp_type>(
+      GetFuncAddr("strcasecmp", (uptr)&strcasecmp));
+  REAL(strstr) = reinterpret_cast<strstr_type>(
+      GetFuncAddr("strstr", (uptr)(strstr_type)&strstr));
+  REAL(strcasestr) = reinterpret_cast<strcasestr_type>(
+      GetFuncAddr("strcasestr", (uptr)(strcasestr_type)&strcasestr));
+  REAL(memmem) =
+      reinterpret_cast<memmem_type>(GetFuncAddr("memmem", (uptr)&memmem));
+}
+
+__attribute__((section(".preinit_array"), used)) static void (
+    *__local_fuzzer_preinit)(void) = __fuzzer_init;
+}
+
+#endif
Index: compiler-rt/lib/fuzzer/CMakeLists.txt
===================================================================
--- compiler-rt/lib/fuzzer/CMakeLists.txt
+++ compiler-rt/lib/fuzzer/CMakeLists.txt
@@ -99,6 +99,13 @@
   CFLAGS ${LIBFUZZER_CFLAGS}
   DEPS ${LIBFUZZER_DEPS})
 
+add_compiler_rt_object_libraries(RTfuzzer_interceptors
+  OS ${FUZZER_SUPPORTED_OS}
+  ARCHS ${FUZZER_SUPPORTED_ARCH}
+  SOURCES FuzzerInterceptors.cpp
+  CFLAGS ${LIBFUZZER_CFLAGS}
+  DEPS ${LIBFUZZER_DEPS})
+
 add_compiler_rt_runtime(clang_rt.fuzzer
   STATIC
   OS ${FUZZER_SUPPORTED_OS}
@@ -115,6 +122,14 @@
   CFLAGS ${LIBFUZZER_CFLAGS}
   PARENT_TARGET fuzzer)
 
+add_compiler_rt_runtime(clang_rt.fuzzer_interceptors
+  STATIC
+  OS ${FUZZER_SUPPORTED_OS}
+  ARCHS ${FUZZER_SUPPORTED_ARCH}
+  OBJECT_LIBS RTfuzzer_interceptors
+  CFLAGS ${LIBFUZZER_CFLAGS}
+  PARENT_TARGET fuzzer)
+
 if(OS_NAME MATCHES "Linux|Fuchsia" AND
    COMPILER_RT_LIBCXX_PATH AND
    COMPILER_RT_LIBCXXABI_PATH)
@@ -148,7 +163,10 @@
     add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build)
     target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
     add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-build)
+    target_compile_options(RTfuzzer_interceptors.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
+    add_dependencies(RTfuzzer_interceptors.${arch} libcxx_fuzzer_${arch}-build)
     partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch})
+    partially_link_libcxx(fuzzer_interceptors ${LIBCXX_${arch}_PREFIX} ${arch})
     partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch})
   endforeach()
 endif()
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -779,6 +779,9 @@
       !Args.hasArg(options::OPT_shared)) {
 
     addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true);
+    if (SanArgs.needsFuzzerInterceptors())
+      addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer_interceptors", false,
+                          true);
     if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx))
       TC.AddCXXStdlibLibArgs(Args, CmdArgs);
   }
Index: clang/lib/Driver/SanitizerArgs.cpp
===================================================================
--- clang/lib/Driver/SanitizerArgs.cpp
+++ clang/lib/Driver/SanitizerArgs.cpp
@@ -238,6 +238,11 @@
   return TrappingKinds;
 }
 
+bool SanitizerArgs::needsFuzzerInterceptors() const {
+  return needsFuzzer() && !needsAsanRt() && !needsHwasanRt() &&
+         !needsTsanRt() && !needsMsanRt();
+}
+
 bool SanitizerArgs::needsUbsanRt() const {
   // All of these include ubsan.
   if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
Index: clang/include/clang/Driver/SanitizerArgs.h
===================================================================
--- clang/include/clang/Driver/SanitizerArgs.h
+++ clang/include/clang/Driver/SanitizerArgs.h
@@ -74,6 +74,7 @@
            !Sanitizers.has(SanitizerKind::Address) &&
            !Sanitizers.has(SanitizerKind::HWAddress);
   }
+  bool needsFuzzerInterceptors() const;
   bool needsUbsanRt() const;
   bool requiresMinimalRuntime() const { return MinimalRuntime; }
   bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to