Index: lib/asan/tests/asan_mem_test.cc
===================================================================
--- lib/asan/tests/asan_mem_test.cc
+++ lib/asan/tests/asan_mem_test.cc
@@ -10,6 +10,11 @@
 //
 //===----------------------------------------------------------------------===//
 #include "asan_test_utils.h"
+#if defined(_GNU_SOURCE) || defined(__FreeBSD__)
+#include <strings.h>  // for bcmp
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+#include <string.h>  // for bcmp
+#endif
 #include <vector>
 
 template<typename T>
@@ -205,37 +210,45 @@
   MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024);
 }
 
-
-TEST(AddressSanitizer, MemCmpOOBTest) {
+template <int(*cmpfn)(const void*, const void*, size_t)>
+void CmpOOBTestCommon() {
   size_t size = Ident(100);
   char *s1 = MallocAndMemsetString(size);
   char *s2 = MallocAndMemsetString(size);
-  // Normal memcmp calls.
-  Ident(memcmp(s1, s2, size));
-  Ident(memcmp(s1 + size - 1, s2 + size - 1, 1));
-  Ident(memcmp(s1 - 1, s2 - 1, 0));
+  // Normal cmpfn calls.
+  Ident(cmpfn(s1, s2, size));
+  Ident(cmpfn(s1 + size - 1, s2 + size - 1, 1));
+  Ident(cmpfn(s1 - 1, s2 - 1, 0));
   // One of arguments points to not allocated memory.
-  EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
-  EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
-  EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
-  EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
+  EXPECT_DEATH(Ident(cmpfn)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
+  EXPECT_DEATH(Ident(cmpfn)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
+  EXPECT_DEATH(Ident(cmpfn)(s1 + size, s2, 1), RightOOBReadMessage(0));
+  EXPECT_DEATH(Ident(cmpfn)(s1, s2 + size, 1), RightOOBReadMessage(0));
   // Hit unallocated memory and die.
-  EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
-  EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
+  EXPECT_DEATH(Ident(cmpfn)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
+  EXPECT_DEATH(Ident(cmpfn)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
   // Zero bytes are not terminators and don't prevent from OOB.
   s1[size - 1] = '\0';
   s2[size - 1] = '\0';
-  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
+  EXPECT_DEATH(Ident(cmpfn)(s1, s2, size + 1), RightOOBReadMessage(0));
 
   // Even if the buffers differ in the first byte, we still assume that
-  // memcmp may access the whole buffer and thus reporting the overflow here:
+  // cmpfn may access the whole buffer and thus reporting the overflow here:
   s1[0] = 1;
   s2[0] = 123;
-  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
+  EXPECT_DEATH(Ident(cmpfn)(s1, s2, size + 1), RightOOBReadMessage(0));
 
   free(s1);
   free(s2);
 }
 
+TEST(AddressSanitizer, MemCmpOOBTest) {
+  CmpOOBTestCommon<memcmp>();
+}
 
-
+TEST(AddressSanitizer, BCmpOOBTest) {
+#if defined(_GNU_SOURCE) || defined(__NetBSD__) || defined(__FreeBSD__) || \
+    defined(__OpenBSD__)
+  CmpOOBTestCommon<bcmp>();
+#endif
+}
Index: lib/sanitizer_common/sanitizer_common_interceptors.inc
===================================================================
--- lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -865,6 +865,49 @@
 #define INIT_MEMCMP
 #endif
 
+#if SANITIZER_INTERCEPT_BCMP
+
+INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {
+  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+    return internal_memcmp(a1, a2, size);  // memcmp() is an ok bcmp() impl.
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size);
+  if (common_flags()->intercept_memcmp) {
+    if (common_flags()->strict_memcmp) {
+      // Check the entire regions even if the first bytes of the buffers are
+      // different.
+      COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
+      COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
+      // Fallthrough to REAL(bcmp) below.
+    } else {
+      unsigned char c1 = 0, c2 = 0;
+      const unsigned char *s1 = (const unsigned char*)a1;
+      const unsigned char *s2 = (const unsigned char*)a2;
+      uptr i;
+      for (i = 0; i < size; i++) {
+        c1 = s1[i];
+        c2 = s2[i];
+        if (c1 != c2) break;
+      }
+      COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
+      COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
+      int r = CharCmpX(c1, c2);
+      CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
+                                 a1, a2, size, r);
+      return r;
+    }
+  }
+  int result = REAL(bcmp(a1, a2, size));
+  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
+                             a2, size, result);
+  return result;
+}
+
+#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp)
+#else
+#define INIT_BCMP
+#endif
+
 #if SANITIZER_INTERCEPT_MEMCHR
 INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
@@ -9473,6 +9516,7 @@
   INIT_MEMCPY;
   INIT_MEMCHR;
   INIT_MEMCMP;
+  INIT_BCMP;
   INIT_MEMRCHR;
   INIT_MEMMEM;
   INIT_READ;
Index: lib/sanitizer_common/sanitizer_platform_interceptors.h
===================================================================
--- lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -142,6 +142,9 @@
 #define SANITIZER_INTERCEPT_MEMMOVE 1
 #define SANITIZER_INTERCEPT_MEMCPY 1
 #define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_BCMP SANITIZER_INTERCEPT_MEMCMP && ( \
+    (SI_POSIX && _GNU_SOURCE) || \
+    SI_NETBSD || SI_OPENBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_STRNDUP SI_POSIX
 #define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD
 #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
Index: test/asan/TestCases/Posix/bcmp_test.cc
===================================================================
--- /dev/null
+++ test/asan/TestCases/Posix/bcmp_test.cc
@@ -0,0 +1,17 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: compiler-rt-optimized
+
+#include <string.h>
+int main(int argc, char **argv) {
+  char a1[] = {static_cast<char>(argc), 2, 3, 4};
+  char a2[] = {1, static_cast<char>(2*argc), 3, 4};
+  int res = bcmp(a1, a2, 4 + argc);  // BOOM
+  // CHECK: AddressSanitizer: stack-buffer-overflow
+  // CHECK: {{#0.*bcmp}}
+  // CHECK: {{#1.*main}}
+  return res;
+}
Index: test/sanitizer_common/TestCases/Posix/weak_hook_test.cc
===================================================================
--- test/sanitizer_common/TestCases/Posix/weak_hook_test.cc
+++ test/sanitizer_common/TestCases/Posix/weak_hook_test.cc
@@ -6,8 +6,11 @@
 // XFAIL: lsan
 // XFAIL: ubsan
 
-#include <string.h>
 #include <assert.h>
+#include <string.h>
+#if defined(_GNU_SOURCE) || defined(__FreeBSD__)
+#include <strings.h>  // for bcmp
+#endif
 
 bool seen_memcmp, seen_strncmp, seen_strncasecmp, seen_strcmp, seen_strcasecmp,
     seen_strstr, seen_strcasestr, seen_memmem;
@@ -59,6 +62,13 @@
   int_sink = memcmp(s1, s2, sizeof(s2));
   assert(seen_memcmp);
 
+#if defined(_GNU_SOURCE) || defined(__NetBSD__) || defined(__FreeBSD__) || \
+    defined(__OpenBSD__)
+  seen_memcmp = false;
+  int_sink = bcmp(s1, s2, sizeof(s2));
+  assert(seen_memcmp);
+#endif
+
   int_sink = strncmp(s1, s2, sizeof(s2));
   assert(seen_strncmp);