[llvm-commits] [compiler-rt] r147316 - in /compiler-rt/trunk/lib/asan: asan_interceptors.cc asan_interceptors.h mach_override/mach_override.c tests/asan_test.cc

Kostya Serebryany kcc at google.com
Wed Dec 28 11:08:49 PST 2011


Author: kcc
Date: Wed Dec 28 13:08:49 2011
New Revision: 147316

URL: http://llvm.org/viewvc/llvm-project?rev=147316&view=rev
Log:
[asan] interceptor for strcat. 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/mach_override/mach_override.c
    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=147316&r1=147315&r2=147316&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Wed Dec 28 13:08:49 2011
@@ -33,6 +33,7 @@
 memmove_f     real_memmove;
 memset_f      real_memset;
 strcasecmp_f  real_strcasecmp;
+strcat_f      real_strcat;
 strchr_f      real_strchr;
 strcmp_f      real_strcmp;
 strcpy_f      real_strcpy;
@@ -80,18 +81,17 @@
 // Behavior of functions like "memcpy" or "strcpy" is undefined
 // if memory intervals overlap. We report error in this case.
 // Macro is used to avoid creation of new frames.
-static inline bool RangesOverlap(const char *offset1, const char *offset2,
-                                 size_t length) {
-  return !((offset1 + length <= offset2) || (offset2 + length <= offset1));
+static inline bool RangesOverlap(const char *offset1, size_t length1,
+                                 const char *offset2, size_t length2) {
+  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
 }
-#define CHECK_RANGES_OVERLAP(_offset1, _offset2, length) do { \
+#define CHECK_RANGES_OVERLAP(_offset1, length1, _offset2, length2) do { \
   const char *offset1 = (const char*)_offset1; \
   const char *offset2 = (const char*)_offset2; \
-  if (RangesOverlap((const char*)offset1, (const char*)offset2, \
-                    length)) { \
+  if (RangesOverlap(offset1, length1, offset2, length2)) { \
     Report("ERROR: AddressSanitizer strcpy-param-overlap: " \
            "memory ranges [%p,%p) and [%p, %p) overlap\n", \
-           offset1, offset1 + length, offset2, offset2 + length); \
+           offset1, offset1 + length1, offset2, offset2 + length2); \
     PRINT_CURRENT_STACK(); \
     ShowStatsAndAbort(); \
   } \
@@ -130,6 +130,7 @@
   INTERCEPT_FUNCTION(memmove);
   INTERCEPT_FUNCTION(memset);
   INTERCEPT_FUNCTION(strcasecmp);
+  INTERCEPT_FUNCTION(strcat);  // NOLINT
   INTERCEPT_FUNCTION(strchr);
   INTERCEPT_FUNCTION(strcmp);
   INTERCEPT_FUNCTION(strcpy);  // NOLINT
@@ -185,7 +186,7 @@
   }
   ENSURE_ASAN_INITED();
   if (FLAG_replace_intrin) {
-    CHECK_RANGES_OVERLAP(to, from, size);
+    CHECK_RANGES_OVERLAP(to, size, from, size);
     ASAN_WRITE_RANGE(from, size);
     ASAN_READ_RANGE(to, size);
   }
@@ -246,6 +247,21 @@
   return CharCaseCmp(c1, c2);
 }
 
+char *WRAP(strcat)(char *to, const char *from) {  // NOLINT
+  ENSURE_ASAN_INITED();
+  if (FLAG_replace_str) {
+    size_t from_length = real_strlen(from);
+    ASAN_READ_RANGE(from, from_length + 1);
+    if (from_length > 0) {
+      size_t to_length = real_strlen(to);
+      ASAN_READ_RANGE(to, to_length);
+      ASAN_WRITE_RANGE(to + to_length, from_length + 1);
+      CHECK_RANGES_OVERLAP(to, to_length + 1, from, from_length + 1);
+    }
+  }
+  return real_strcat(to, from);
+}
+
 int WRAP(strcmp)(const char *s1, const char *s2) {
   // strcmp is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.
@@ -273,7 +289,7 @@
   ENSURE_ASAN_INITED();
   if (FLAG_replace_str) {
     size_t from_size = real_strlen(from) + 1;
-    CHECK_RANGES_OVERLAP(to, from, from_size);
+    CHECK_RANGES_OVERLAP(to, from_size, from, from_size);
     ASAN_READ_RANGE(from, from_size);
     ASAN_WRITE_RANGE(to, from_size);
   }
@@ -339,7 +355,7 @@
   ENSURE_ASAN_INITED();
   if (FLAG_replace_str) {
     size_t from_size = Min(size, internal_strnlen(from, size) + 1);
-    CHECK_RANGES_OVERLAP(to, from, from_size);
+    CHECK_RANGES_OVERLAP(to, from_size, from, from_size);
     ASAN_READ_RANGE(from, from_size);
     ASAN_WRITE_RANGE(to, size);
   }

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=147316&r1=147315&r2=147316&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.h Wed Dec 28 13:08:49 2011
@@ -72,6 +72,7 @@
 void *WRAP(memmove)(void *to, const void *from, size_t size);
 void *WRAP(memset)(void *block, int c, size_t size);
 int WRAP(strcasecmp)(const char *s1, const char *s2);
+char *WRAP(strcat)(char *to, const char *from);  // NOLINT
 char *WRAP(strchr)(const char *string, int c);
 int WRAP(strcmp)(const char *s1, const char *s2);
 char *WRAP(strcpy)(char *to, const char *from);  // NOLINT
@@ -90,6 +91,7 @@
 typedef void* (*memmove_f)(void *to, const void *from, size_t size);
 typedef void* (*memset_f)(void *block, int c, size_t size);
 typedef int (*strcasecmp_f)(const char *s1, const char *s2);
+typedef char* (*strcat_f)(char *to, const char *from);
 typedef char* (*strchr_f)(const char *str, int c);
 typedef int (*strcmp_f)(const char *s1, const char *s2);
 typedef char* (*strcpy_f)(char *to, const char *from);
@@ -107,6 +109,7 @@
 extern memmove_f        real_memmove;
 extern memset_f         real_memset;
 extern strcasecmp_f     real_strcasecmp;
+extern strcat_f         real_strcat;
 extern strchr_f         real_strchr;
 extern strcmp_f         real_strcmp;
 extern strcpy_f         real_strcpy;

Modified: compiler-rt/trunk/lib/asan/mach_override/mach_override.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/mach_override/mach_override.c?rev=147316&r1=147315&r2=147316&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/mach_override/mach_override.c (original)
+++ compiler-rt/trunk/lib/asan/mach_override/mach_override.c Wed Dec 28 13:08:49 2011
@@ -627,6 +627,7 @@
 	{ 0x2, {0xFF, 0xFF}, {0x31, 0xC0} },						// xor %eax, %eax
 	{ 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} },  // mov $imm(%ebp), %reg
 	{ 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} },  // mov $imm(%eax-%edx), %reg
+	{ 0x3, {0xFF, 0xCF, 0x00}, {0x8B, 0x4D, 0x00} },  // mov $imm(%rpb), %reg
 	{ 0x3, {0xFF, 0x4F, 0x00}, {0x8A, 0x4D, 0x00} },  // mov $imm(%ebp), %cl
 	{ 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} },  			// mov $imm(%esp), %ecx
 	{ 0x4, {0xFF, 0x00, 0x00, 0x00}, {0x8B, 0x00, 0x00, 0x00} },  			// mov r16,r/m16 or r32,r/m32

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=147316&r1=147315&r2=147316&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Wed Dec 28 13:08:49 2011
@@ -1324,6 +1324,39 @@
   free(s2);
 }
 
+TEST(AddressSanitizer, StrCatOOBTest) {
+  size_t to_size = Ident(100);
+  char *to = MallocAndMemsetString(to_size);
+  to[0] = '\0';
+  size_t from_size = Ident(20);
+  char *from = MallocAndMemsetString(from_size);
+  from[from_size - 1] = '\0';
+  // Normal strcat calls.
+  strcat(to, from);
+  strcat(to, from);
+  strcat(to + from_size, from + from_size - 2);
+  // Catenate empty string is not always an error.
+  strcat(to - 1, from + from_size - 1);
+  // One of arguments points to not allocated memory.
+  EXPECT_DEATH(strcat(to - 1, from), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(strcat(to, from - 1), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(strcat(to + to_size, from), RightOOBErrorMessage(0));
+  EXPECT_DEATH(strcat(to, from + from_size), RightOOBErrorMessage(0));
+
+  // "from" is not zero-terminated.
+  from[from_size - 1] = 'z';
+  EXPECT_DEATH(strcat(to, from), RightOOBErrorMessage(0));
+  from[from_size - 1] = '\0';
+  // "to" is not zero-terminated.
+  memset(to, 'z', to_size);
+  EXPECT_DEATH(strcat(to, from), RightOOBErrorMessage(0));
+  // "to" is too short to fit "from".
+  to[to_size - from_size + 1] = '\0';
+  EXPECT_DEATH(strcat(to, from), RightOOBErrorMessage(0));
+  // length of "to" is just enough.
+  strcat(to, from + 1);
+}
+
 static const char *kOverlapErrorMessage = "strcpy-param-overlap";
 
 TEST(AddressSanitizer, StrArgsOverlapTest) {
@@ -1357,6 +1390,18 @@
   strncpy(str + 11, str, 20);
   EXPECT_DEATH(strncpy(str + 10, str, 20), kOverlapErrorMessage);
 
+  // Check "strcat".
+  memset(str, 'z', size);
+  str[10] = '\0';
+  str[20] = '\0';
+  strcat(str, str + 10);
+  strcat(str, str + 11);
+  str[10] = '\0';
+  strcat(str + 11, str);
+  EXPECT_DEATH(strcat(str, str + 9), kOverlapErrorMessage);
+  EXPECT_DEATH(strcat(str + 9, str), kOverlapErrorMessage);
+  EXPECT_DEATH(strcat(str + 10, str), kOverlapErrorMessage);
+
   free(str);
 }
 





More information about the llvm-commits mailing list