[llvm-commits] [compiler-rt] r147315 - in /compiler-rt/trunk/lib/asan: asan_interceptors.cc asan_interceptors.h asan_stack.cc tests/asan_test.cc

Kostya Serebryany kcc at google.com
Wed Dec 28 10:56:43 PST 2011


Author: kcc
Date: Wed Dec 28 12:56:42 2011
New Revision: 147315

URL: http://llvm.org/viewvc/llvm-project?rev=147315&view=rev
Log:
[asan] interceptor for memcmp. Patch by samsonov at google.com

Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_interceptors.h
    compiler-rt/trunk/lib/asan/asan_stack.cc
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=147315&r1=147314&r2=147315&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Wed Dec 28 12:56:42 2011
@@ -28,6 +28,7 @@
 namespace __asan {
 
 index_f       real_index;
+memcmp_f      real_memcmp;
 memcpy_f      real_memcpy;
 memmove_f     real_memmove;
 memset_f      real_memset;
@@ -124,6 +125,7 @@
 #else
   OVERRIDE_FUNCTION(index, WRAP(strchr));
 #endif
+  INTERCEPT_FUNCTION(memcmp);
   INTERCEPT_FUNCTION(memcpy);
   INTERCEPT_FUNCTION(memmove);
   INTERCEPT_FUNCTION(memset);
@@ -149,6 +151,32 @@
 // ---------------------- Wrappers ---------------- {{{1
 using namespace __asan;  // NOLINT
 
+static inline int CharCmp(unsigned char c1, unsigned char c2) {
+  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
+}
+
+static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
+  int c1_low = tolower(c1);
+  int c2_low = tolower(c2);
+  return c1_low - c2_low;
+}
+
+int WRAP(memcmp)(const void *a1, const void *a2, size_t size) {
+  ENSURE_ASAN_INITED();
+  unsigned char c1 = 0, c2 = 0;
+  const unsigned char *s1 = (const unsigned char*)a1;
+  const unsigned char *s2 = (const unsigned char*)a2;
+  size_t i;
+  for (i = 0; i < size; i++) {
+    c1 = s1[i];
+    c2 = s2[i];
+    if (c1 != c2) break;
+  }
+  ASAN_READ_RANGE(s1, Min(i + 1, size));
+  ASAN_READ_RANGE(s2, Min(i + 1, size));
+  return CharCmp(c1, c2);
+}
+
 void *WRAP(memcpy)(void *to, const void *from, size_t size) {
   // memcpy is called during __asan_init() from the internals
   // of printf(...).
@@ -204,16 +232,6 @@
   return result;
 }
 
-static inline int CharCmp(unsigned char c1, unsigned char c2) {
-  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
-}
-
-static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
-  int c1_low = tolower(c1);
-  int c2_low = tolower(c2);
-  return c1_low - c2_low;
-}
-
 int WRAP(strcasecmp)(const char *s1, const char *s2) {
   ENSURE_ASAN_INITED();
   unsigned char c1, c2;

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.h?rev=147315&r1=147314&r2=147315&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.h Wed Dec 28 12:56:42 2011
@@ -67,6 +67,7 @@
 #endif
 
 #ifdef __APPLE__
+int WRAP(memcmp)(const void *a1, const void *a2, size_t size);
 void *WRAP(memcpy)(void *to, const void *from, size_t size);
 void *WRAP(memmove)(void *to, const void *from, size_t size);
 void *WRAP(memset)(void *block, int c, size_t size);
@@ -84,6 +85,7 @@
 namespace __asan {
 
 typedef void* (*index_f)(const char *string, int c);
+typedef int (*memcmp_f)(const void *a1, const void *a2, size_t size);
 typedef void* (*memcpy_f)(void *to, const void *from, size_t size);
 typedef void* (*memmove_f)(void *to, const void *from, size_t size);
 typedef void* (*memset_f)(void *block, int c, size_t size);
@@ -100,6 +102,7 @@
 
 // __asan::real_X() holds pointer to library implementation of X().
 extern index_f          real_index;
+extern memcmp_f         real_memcmp;
 extern memcpy_f         real_memcpy;
 extern memmove_f        real_memmove;
 extern memset_f         real_memset;

Modified: compiler-rt/trunk/lib/asan/asan_stack.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_stack.cc?rev=147315&r1=147314&r2=147315&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_stack.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_stack.cc Wed Dec 28 12:56:42 2011
@@ -230,8 +230,8 @@
   // |res| may be greater than check_stack.size, because
   // UncompressStack(CompressStack(stack)) eliminates the 0x0 frames.
   CHECK(res >= check_stack.size);
-  CHECK(0 == memcmp(check_stack.trace, stack->trace,
-                    check_stack.size * sizeof(uintptr_t)));
+  CHECK(0 == real_memcmp(check_stack.trace, stack->trace,
+                         check_stack.size * sizeof(uintptr_t)));
 #endif
 
   return res;

Modified: compiler-rt/trunk/lib/asan/tests/asan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_test.cc?rev=147315&r1=147314&r2=147315&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Wed Dec 28 12:56:42 2011
@@ -1220,6 +1220,14 @@
   EXPECT_LT(0, strncasecmp("xyz", "xyy", 10));
   EXPECT_LT(0, strncasecmp("Baa", "aaa", 1));
   EXPECT_LT(0, strncasecmp("zyx", "", 2));
+
+  // memcmp
+  EXPECT_EQ(0, memcmp("a", "b", 0));
+  EXPECT_EQ(0, memcmp("ab\0c", "ab\0c", 4));
+  EXPECT_GT(0, memcmp("\0ab", "\0ac", 3));
+  EXPECT_GT(0, memcmp("abb\0", "abba", 4));
+  EXPECT_LT(0, memcmp("ab\0cd", "ab\0c\0", 5));
+  EXPECT_LT(0, memcmp("zza", "zyx", 3));
 }
 
 typedef int(*PointerToStrCmp)(const char*, const char*);
@@ -1292,6 +1300,30 @@
   RunStrNCmpTest(&strncasecmp);
 }
 
+TEST(AddressSanitizer, MemCmpOOBTest) {
+  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));
+  // One of arguments points to not allocated memory.
+  EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBErrorMessage(0));
+  // Hit unallocated memory and die.
+  EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBErrorMessage(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), RightOOBErrorMessage(0));
+  free(s1);
+  free(s2);
+}
+
 static const char *kOverlapErrorMessage = "strcpy-param-overlap";
 
 TEST(AddressSanitizer, StrArgsOverlapTest) {





More information about the llvm-commits mailing list