[libFuzzer] Instrument bcmp

If we define memcmp in an archive, bcmp should be defined as well (many libc
define bcmp/memcmp in one object file).  Otherwise if the application calls bcmp
or strcmp which gets optimized to bcmp (SimplifyLibCalls), the undefined
reference may pull in an optimized bcmp/strcmp implementation (libc replacement)
later on the linker command line.  If both libFuzzer's memcmp and the optimized
memcmp are strong => there will be a multiple definition error.

GitOrigin-RevId: f7ffb122d08e7a8203557898c67eaac3a857b152
diff --git a/FuzzerInterceptors.cpp b/FuzzerInterceptors.cpp
index 0afc96c..a1a6478 100644
--- a/FuzzerInterceptors.cpp
+++ b/FuzzerInterceptors.cpp
@@ -119,6 +119,7 @@
 
 extern "C" {
 
+DEFINE_REAL(int, bcmp, const void *, const void *, size_t)
 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 *)
@@ -128,6 +129,14 @@
 DEFINE_REAL(char *, strcasestr, const char *, const char *)
 DEFINE_REAL(void *, memmem, const void *, size_t, const void *, size_t)
 
+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);
+  return result;
+}
+
 ATTRIBUTE_INTERFACE int memcmp(const void *s1, const void *s2, size_t n) {
   if (!FuzzerInited)
     return internal_memcmp(s1, s2, n);
@@ -200,6 +209,8 @@
     return;
   FuzzerInitIsRunning = true;
 
+  REAL(bcmp) = reinterpret_cast<memcmp_type>(
+      getFuncAddr("bcmp", reinterpret_cast<uintptr_t>(&bcmp)));
   REAL(memcmp) = reinterpret_cast<memcmp_type>(
       getFuncAddr("memcmp", reinterpret_cast<uintptr_t>(&memcmp)));
   REAL(strncmp) = reinterpret_cast<strncmp_type>(