[clang] b52b2e1 - Recommit "[libFuzzer] Disable implicit builtin knowledge about memcmp-like functions when -fsanitize=fuzzer-no-link is given."

2020-07-27 Thread Dokyung Song via cfe-commits

Author: Dokyung Song
Date: 2020-07-27T18:27:49Z
New Revision: b52b2e1c188072e3cbc91500cfd503fb26d50ffc

URL: 
https://github.com/llvm/llvm-project/commit/b52b2e1c188072e3cbc91500cfd503fb26d50ffc
DIFF: 
https://github.com/llvm/llvm-project/commit/b52b2e1c188072e3cbc91500cfd503fb26d50ffc.diff

LOG: Recommit "[libFuzzer] Disable implicit builtin knowledge about memcmp-like 
functions when -fsanitize=fuzzer-no-link is given."

Summary: This patch disables implicit builtin knowledge about memcmp-like 
functions when compiling the program for fuzzing, i.e., when 
-fsanitize=fuzzer(-no-link) is given. This allows libFuzzer to always intercept 
memcmp-like functions as it effectively disables optimizing calls to such 
functions into different forms. This is done by adding a set of flags 
(-fno-builtin-memcmp and others) in the clang driver. Individual -fno-builtin-* 
flags previously used in several libFuzzer tests are now removed, as it is now 
done automatically in the clang driver.

The patch was once reverted in 8ef9e2bf355d05bc81d8b0fe1e5333eec59a0a91, as 
this patch was dependent on a reverted commit 
f78d9fceea736d431e9e3cbca291e3909e3aa46d. This reverted commit was recommitted 
in 831ae45e3dc609e43ba561af07670a8fe47461ef, so relanding this dependent patch 
too.

Reviewers: morehouse, hctim

Subscribers: cfe-commits, #sanitizers

Tags: #clang, #sanitizers

Differential Revision: https://reviews.llvm.org/D83987

Added: 
compiler-rt/test/fuzzer/noasan-bcmp.test

Modified: 
clang/lib/Driver/SanitizerArgs.cpp
compiler-rt/test/fuzzer/noasan-memcmp.test
compiler-rt/test/fuzzer/noasan-memcmp64.test
compiler-rt/test/fuzzer/noasan-strcmp.test
compiler-rt/test/fuzzer/noasan-strncmp.test
compiler-rt/test/fuzzer/noasan-strstr.test

Removed: 




diff  --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index e4fda752c041..8c49e92b2c0f 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -1088,6 +1088,23 @@ void SanitizerArgs::addArgs(const ToolChain , const 
llvm::opt::ArgList ,
   Sanitizers.has(SanitizerKind::Address))
 CmdArgs.push_back("-fno-assume-sane-operator-new");
 
+  // libFuzzer wants to intercept calls to certain library functions, so the
+  // following -fno-builtin-* flags force the compiler to emit interposable
+  // libcalls to these functions. Other sanitizers effectively do the same 
thing
+  // by marking all library call sites with NoBuiltin attribute in their LLVM
+  // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
+  if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
+CmdArgs.push_back("-fno-builtin-bcmp");
+CmdArgs.push_back("-fno-builtin-memcmp");
+CmdArgs.push_back("-fno-builtin-strncmp");
+CmdArgs.push_back("-fno-builtin-strcmp");
+CmdArgs.push_back("-fno-builtin-strncasecmp");
+CmdArgs.push_back("-fno-builtin-strcasecmp");
+CmdArgs.push_back("-fno-builtin-strstr");
+CmdArgs.push_back("-fno-builtin-strcasestr");
+CmdArgs.push_back("-fno-builtin-memmem");
+  }
+
   // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
   // enabled.
   if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&

diff  --git a/compiler-rt/test/fuzzer/noasan-bcmp.test 
b/compiler-rt/test/fuzzer/noasan-bcmp.test
new file mode 100644
index ..a3dd17bf6e2b
--- /dev/null
+++ b/compiler-rt/test/fuzzer/noasan-bcmp.test
@@ -0,0 +1,4 @@
+UNSUPPORTED: darwin, freebsd, windows
+RUN: %cpp_compiler -fno-sanitize=address -DMEMCMP=bcmp %S/MemcmpTest.cpp -o %t
+RUN: not %run %t -seed=1 -runs=1000 2>&1 | FileCheck %s
+CHECK: BINGO

diff  --git a/compiler-rt/test/fuzzer/noasan-memcmp.test 
b/compiler-rt/test/fuzzer/noasan-memcmp.test
index c90755c53a90..c5ce2fff8c9f 100644
--- a/compiler-rt/test/fuzzer/noasan-memcmp.test
+++ b/compiler-rt/test/fuzzer/noasan-memcmp.test
@@ -1,9 +1,9 @@
 UNSUPPORTED: darwin, freebsd, windows
 
-RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-memcmp %S/MemcmpTest.cpp 
-o %t-NoAsanMemcmpTest
+RUN: %cpp_compiler -fno-sanitize=address %S/MemcmpTest.cpp -o 
%t-NoAsanMemcmpTest
 RUN: not %run %t-NoAsanMemcmpTest -seed=1 -runs=1000   2>&1 | FileCheck %s
 
-RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-calloc 
-fno-builtin-memcmp %S/CustomAllocator.cpp %S/MemcmpTest.cpp -o 
%t-NoAsanCustomAllocatorMemcmpTest
+RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-calloc 
%S/CustomAllocator.cpp %S/MemcmpTest.cpp -o %t-NoAsanCustomAllocatorMemcmpTest
 RUN: not %run %t-NoAsanCustomAllocatorMemcmpTest -seed=1 -runs=1000   2>&1 
| FileCheck %s
 
 CHECK: BINGO

diff  --git a/compiler-rt/test/fuzzer/noasan-memcmp64.test 
b/compiler-rt/test/fuzzer/noasan-memcmp64.test
index a6b8f88594d0..496ee386193e 100644
--- a/compiler-rt/test/fuzzer/noasan-memcmp64.test
+++ b/compiler-rt/test/fuzzer/noasan-memcmp64.test
@@ 

[clang] 831ae45 - Recommit "[libFuzzer] Link libFuzzer's own interceptors when other compiler runtimes are not linked."

2020-07-23 Thread Dokyung Song via cfe-commits

Author: Dokyung Song
Date: 2020-07-23T15:59:07Z
New Revision: 831ae45e3dc609e43ba561af07670a8fe47461ef

URL: 
https://github.com/llvm/llvm-project/commit/831ae45e3dc609e43ba561af07670a8fe47461ef
DIFF: 
https://github.com/llvm/llvm-project/commit/831ae45e3dc609e43ba561af07670a8fe47461ef.diff

LOG: Recommit "[libFuzzer] Link libFuzzer's own interceptors when other 
compiler runtimes are not linked."

Summary: libFuzzer intercepts certain library functions such as memcmp/strcmp 
by defining weak hooks. Weak hooks, however, are called only when other 
runtimes such as ASan is linked. This patch defines libFuzzer's own 
interceptors, which is linked into the libFuzzer executable when other runtimes 
are not linked, i.e., when -fsanitize=fuzzer is given, but not others.

The patch once landed but was reverted in 
8ef9e2bf355d05bc81d8b0fe1e5333eec59a0a91 due to an assertion failure caused by 
calling an intercepted function, strncmp, while initializing the interceptors 
in fuzzerInit(). This issue is now fixed by calling libFuzzer's own 
implementation of library functions (i.e., internal_*) when the fuzzer has not 
been initialized yet, instead of recursively calling fuzzerInit() again.

Reviewers: kcc, morehouse, hctim

Subscribers: #sanitizers, krytarowski, mgorny, cfe-commits

Tags: #clang, #sanitizers

Differential Revision: https://reviews.llvm.org/D83494

Added: 
compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
compiler-rt/test/fuzzer/CustomAllocator.cpp
compiler-rt/test/fuzzer/custom-allocator.test

Modified: 
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/test/fuzzer/memcmp.test
compiler-rt/test/fuzzer/memcmp64.test
compiler-rt/test/fuzzer/strcmp.test
compiler-rt/test/fuzzer/strncmp.test
compiler-rt/test/fuzzer/strstr.test

Removed: 




diff  --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 934dab808e82..563d6c3ff9de 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -74,6 +74,7 @@ class SanitizerArgs {
!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); }

diff  --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index bcc9ffc7ff8f..e4fda752c041 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -240,6 +240,10 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver ,
   return TrappingKinds;
 }
 
+bool SanitizerArgs::needsFuzzerInterceptors() const {
+  return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
+}
+
 bool SanitizerArgs::needsUbsanRt() const {
   // All of these include ubsan.
   if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 6b6e276b8ce7..acde6d9e2111 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -784,6 +784,9 @@ bool tools::addSanitizerRuntimes(const ToolChain , const 
ArgList ,
   !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);
   }

diff  --git a/compiler-rt/lib/fuzzer/CMakeLists.txt 
b/compiler-rt/lib/fuzzer/CMakeLists.txt
index b5be6b89452e..02be89cb70a5 100644
--- a/compiler-rt/lib/fuzzer/CMakeLists.txt
+++ b/compiler-rt/lib/fuzzer/CMakeLists.txt
@@ -99,6 +99,13 @@ add_compiler_rt_object_libraries(RTfuzzer_main
   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 @@ add_compiler_rt_runtime(clang_rt.fuzzer_no_main
   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

[clang] 12d1124 - [libFuzzer] Disable implicit builtin knowledge about memcmp-like functions when -fsanitize=fuzzer-no-link is given.

2020-07-16 Thread Dokyung Song via cfe-commits

Author: Dokyung Song
Date: 2020-07-16T22:53:54Z
New Revision: 12d1124c49beec0fb79d36944960e5bf0f236d4c

URL: 
https://github.com/llvm/llvm-project/commit/12d1124c49beec0fb79d36944960e5bf0f236d4c
DIFF: 
https://github.com/llvm/llvm-project/commit/12d1124c49beec0fb79d36944960e5bf0f236d4c.diff

LOG: [libFuzzer] Disable implicit builtin knowledge about memcmp-like functions 
when -fsanitize=fuzzer-no-link is given.

Summary: This patch disables implicit builtin knowledge about memcmp-like 
functions when compiling the program for fuzzing, i.e., when 
-fsanitize=fuzzer(-no-link) is given. This allows libFuzzer to always intercept 
memcmp-like functions as it effectively disables optimizing calls to such 
functions into different forms. This is done by adding a set of flags 
(-fno-builtin-memcmp and others) in the clang driver. Individual -fno-builtin-* 
flags previously used in several libFuzzer tests are now removed, as it is now 
done automatically in the clang driver.

Reviewers: morehouse, hctim

Subscribers: cfe-commits, #sanitizers

Tags: #clang, #sanitizers

Differential Revision: https://reviews.llvm.org/D83987

Added: 


Modified: 
clang/lib/Driver/SanitizerArgs.cpp
compiler-rt/test/fuzzer/memcmp.test
compiler-rt/test/fuzzer/memcmp64.test
compiler-rt/test/fuzzer/strcmp.test
compiler-rt/test/fuzzer/strncmp.test
compiler-rt/test/fuzzer/strstr.test

Removed: 




diff  --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index e4fda752c041..4af24662ca91 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -1088,6 +1088,22 @@ void SanitizerArgs::addArgs(const ToolChain , const 
llvm::opt::ArgList ,
   Sanitizers.has(SanitizerKind::Address))
 CmdArgs.push_back("-fno-assume-sane-operator-new");
 
+  // libFuzzer wants to intercept calls to certain library functions, so the
+  // following -fno-builtin-* flags force the compiler to emit interposable
+  // libcalls to these functions. Other sanitizers effectively do the same 
thing
+  // by marking all library call sites with NoBuiltin attribute in their LLVM
+  // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
+  if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
+CmdArgs.push_back("-fno-builtin-memcmp");
+CmdArgs.push_back("-fno-builtin-strncmp");
+CmdArgs.push_back("-fno-builtin-strcmp");
+CmdArgs.push_back("-fno-builtin-strncasecmp");
+CmdArgs.push_back("-fno-builtin-strcasecmp");
+CmdArgs.push_back("-fno-builtin-strstr");
+CmdArgs.push_back("-fno-builtin-strcasestr");
+CmdArgs.push_back("-fno-builtin-memmem");
+  }
+
   // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
   // enabled.
   if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&

diff  --git a/compiler-rt/test/fuzzer/memcmp.test 
b/compiler-rt/test/fuzzer/memcmp.test
index 8859afbe8a97..fa995a22c68a 100644
--- a/compiler-rt/test/fuzzer/memcmp.test
+++ b/compiler-rt/test/fuzzer/memcmp.test
@@ -2,7 +2,7 @@ UNSUPPORTED: freebsd
 RUN: %cpp_compiler %S/MemcmpTest.cpp -o %t-MemcmpTest
 RUN: not %run %t-MemcmpTest   -seed=1 -runs=1000   2>&1 | 
FileCheck %s
 
-RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-memcmp %S/MemcmpTest.cpp 
-o %t-NoAsanMemcmpTest
+RUN: %cpp_compiler -fno-sanitize=address %S/MemcmpTest.cpp -o 
%t-NoAsanMemcmpTest
 RUN: not %run %t-MemcmpTest   -seed=1 -runs=1000   2>&1 | 
FileCheck %s
 
 CHECK: BINGO

diff  --git a/compiler-rt/test/fuzzer/memcmp64.test 
b/compiler-rt/test/fuzzer/memcmp64.test
index fc9d02324373..ca8c8fe8206f 100644
--- a/compiler-rt/test/fuzzer/memcmp64.test
+++ b/compiler-rt/test/fuzzer/memcmp64.test
@@ -2,7 +2,7 @@ UNSUPPORTED: freebsd
 RUN: %cpp_compiler %S/Memcmp64BytesTest.cpp -o %t-Memcmp64BytesTest
 RUN: not %run %t-Memcmp64BytesTest-seed=1 -runs=100   2>&1 | 
FileCheck %s
 
-RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-memcmp 
%S/Memcmp64BytesTest.cpp -o %t-NoAsanMemcmp64BytesTest
+RUN: %cpp_compiler -fno-sanitize=address %S/Memcmp64BytesTest.cpp -o 
%t-NoAsanMemcmp64BytesTest
 RUN: not %run %t-Memcmp64BytesTest-seed=1 -runs=100   2>&1 | 
FileCheck %s
 
 CHECK: BINGO

diff  --git a/compiler-rt/test/fuzzer/strcmp.test 
b/compiler-rt/test/fuzzer/strcmp.test
index eebcf8ef5c70..61065de6fa94 100644
--- a/compiler-rt/test/fuzzer/strcmp.test
+++ b/compiler-rt/test/fuzzer/strcmp.test
@@ -2,7 +2,7 @@ UNSUPPORTED: freebsd
 RUN: %cpp_compiler %S/StrcmpTest.cpp -o %t-StrcmpTest
 RUN: not %run %t-StrcmpTest   -seed=1 -runs=200   2>&1 | 
FileCheck %s
 
-RUN: %cpp_compiler -fno-sanitize=address -fno-builtin-strcmp %S/StrcmpTest.cpp 
-o %t-NoAsanStrcmpTest
+RUN: %cpp_compiler -fno-sanitize=address %S/StrcmpTest.cpp -o 
%t-NoAsanStrcmpTest
 RUN: not %run %t-StrcmpTest   -seed=1 -runs=200   2>&1 |