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

Kostya Serebryany kcc at google.com
Tue Dec 27 18:24:50 PST 2011


Author: kcc
Date: Tue Dec 27 20:24:50 2011
New Revision: 147304

URL: http://llvm.org/viewvc/llvm-project?rev=147304&view=rev
Log:
[asan] interceptors for strcasecmp and strncasecmp. 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/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=147304&r1=147303&r2=147304&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Tue Dec 27 20:24:50 2011
@@ -20,8 +20,10 @@
 #include "asan_stack.h"
 #include "asan_stats.h"
 
+#include <ctype.h>
 #include <dlfcn.h>
 #include <string.h>
+#include <strings.h>
 
 namespace __asan {
 
@@ -29,11 +31,13 @@
 memcpy_f      real_memcpy;
 memmove_f     real_memmove;
 memset_f      real_memset;
+strcasecmp_f  real_strcasecmp;
 strchr_f      real_strchr;
 strcmp_f      real_strcmp;
 strcpy_f      real_strcpy;
 strdup_f      real_strdup;
 strlen_f      real_strlen;
+strncasecmp_f real_strncasecmp;
 strncmp_f     real_strncmp;
 strncpy_f     real_strncpy;
 strnlen_f     real_strnlen;
@@ -123,11 +127,13 @@
   INTERCEPT_FUNCTION(memcpy);
   INTERCEPT_FUNCTION(memmove);
   INTERCEPT_FUNCTION(memset);
+  INTERCEPT_FUNCTION(strcasecmp);
   INTERCEPT_FUNCTION(strchr);
   INTERCEPT_FUNCTION(strcmp);
   INTERCEPT_FUNCTION(strcpy);  // NOLINT
   INTERCEPT_FUNCTION(strdup);
   INTERCEPT_FUNCTION(strlen);
+  INTERCEPT_FUNCTION(strncasecmp);
   INTERCEPT_FUNCTION(strncmp);
   INTERCEPT_FUNCTION(strncpy);
 #ifndef __APPLE__
@@ -202,6 +208,26 @@
   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;
+  size_t i;
+  for (i = 0; ; i++) {
+    c1 = (unsigned char)s1[i];
+    c2 = (unsigned char)s2[i];
+    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
+  }
+  ASAN_READ_RANGE(s1, i + 1);
+  ASAN_READ_RANGE(s2, i + 1);
+  return CharCaseCmp(c1, c2);
+}
+
 int WRAP(strcmp)(const char *s1, const char *s2) {
   // strcmp is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.
@@ -259,6 +285,20 @@
   return length;
 }
 
+int WRAP(strncasecmp)(const char *s1, const char *s2, size_t size) {
+  ENSURE_ASAN_INITED();
+  unsigned char c1 = 0, c2 = 0;
+  size_t i;
+  for (i = 0; i < size; i++) {
+    c1 = (unsigned char)s1[i];
+    c2 = (unsigned char)s2[i];
+    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
+  }
+  ASAN_READ_RANGE(s1, Min(i + 1, size));
+  ASAN_READ_RANGE(s2, Min(i + 1, size));
+  return CharCaseCmp(c1, c2);
+}
+
 int WRAP(strncmp)(const char *s1, const char *s2, size_t size) {
   // strncmp is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.

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=147304&r1=147303&r2=147304&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.h Tue Dec 27 20:24:50 2011
@@ -70,11 +70,13 @@
 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);
+int WRAP(strcasecmp)(const char *s1, const char *s2);
 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
 char *WRAP(strdup)(const char *s);
 size_t WRAP(strlen)(const char *s);
+int WRAP(strncasecmp)(const char *s1, const char *s2, size_t n);
 int WRAP(strncmp)(const char *s1, const char *s2, size_t size);
 char *WRAP(strncpy)(char *to, const char *from, size_t size);
 #endif
@@ -85,11 +87,13 @@
 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);
+typedef int (*strcasecmp_f)(const char *s1, const char *s2);
 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);
 typedef char* (*strdup_f)(const char *s);
 typedef size_t (*strlen_f)(const char *s);
+typedef int (*strncasecmp_f)(const char *s1, const char *s2, size_t n);
 typedef int (*strncmp_f)(const char *s1, const char *s2, size_t size);
 typedef char* (*strncpy_f)(char *to, const char *from, size_t size);
 typedef size_t (*strnlen_f)(const char *s, size_t maxlen);
@@ -99,11 +103,13 @@
 extern memcpy_f         real_memcpy;
 extern memmove_f        real_memmove;
 extern memset_f         real_memset;
+extern strcasecmp_f     real_strcasecmp;
 extern strchr_f         real_strchr;
 extern strcmp_f         real_strcmp;
 extern strcpy_f         real_strcpy;
 extern strdup_f         real_strdup;
 extern strlen_f         real_strlen;
+extern strncasecmp_f    real_strncasecmp;
 extern strncmp_f        real_strncmp;
 extern strncpy_f        real_strncpy;
 extern strnlen_f        real_strnlen;

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=147304&r1=147303&r2=147304&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Tue Dec 27 20:24:50 2011
@@ -14,6 +14,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <pthread.h>
 #include <stdint.h>
 #include <setjmp.h>
@@ -1050,11 +1051,16 @@
   free(heap_string);
 }
 
+static inline char* MallocAndMemsetString(size_t size) {
+  char *s = Ident((char*)malloc(size));
+  memset(s, 'z', size);
+  return s;
+}
+
 #ifndef __APPLE__
 TEST(AddressSanitizer, StrNLenOOBTest) {
   size_t size = Ident(123);
-  char *str = Ident((char*)malloc(size));
-  memset(str, 'z', size);
+  char *str = MallocAndMemsetString(size);
   // Normal strnlen calls.
   Ident(strnlen(str - 1, 0));
   Ident(strnlen(str, size));
@@ -1073,9 +1079,8 @@
 
 TEST(AddressSanitizer, StrDupOOBTest) {
   size_t size = Ident(42);
-  char *str = Ident((char*)malloc(size));
+  char *str = MallocAndMemsetString(size);
   char *new_str;
-  memset(str, 'z', size);
   // Normal strdup calls.
   str[size - 1] = '\0';
   new_str = strdup(str);
@@ -1157,8 +1162,7 @@
 typedef char*(*PointerToStrChr)(const char*, int);
 void RunStrChrTest(PointerToStrChr StrChr) {
   size_t size = Ident(100);
-  char *str = Ident((char*)malloc(size));
-  memset(str, 'z', size);
+  char *str = MallocAndMemsetString(size);
   str[10] = 'q';
   str[11] = '\0';
   EXPECT_EQ(str, StrChr(str, 'z'));
@@ -1181,81 +1185,113 @@
   // strcmp
   EXPECT_EQ(0, strcmp("", ""));
   EXPECT_EQ(0, strcmp("abcd", "abcd"));
-  EXPECT_EQ(-1, strcmp("ab", "ac"));
-  EXPECT_EQ(-1, strcmp("abc", "abcd"));
-  EXPECT_EQ(1, strcmp("acc", "abc"));
-  EXPECT_EQ(1, strcmp("abcd", "abc"));
+  EXPECT_GT(0, strcmp("ab", "ac"));
+  EXPECT_GT(0, strcmp("abc", "abcd"));
+  EXPECT_LT(0, strcmp("acc", "abc"));
+  EXPECT_LT(0, strcmp("abcd", "abc"));
 
   // strncmp
   EXPECT_EQ(0, strncmp("a", "b", 0));
   EXPECT_EQ(0, strncmp("abcd", "abcd", 10));
   EXPECT_EQ(0, strncmp("abcd", "abcef", 3));
-  EXPECT_EQ(-1, strncmp("abcde", "abcfa", 4));
-  EXPECT_EQ(-1, strncmp("a", "b", 5));
-  EXPECT_EQ(-1, strncmp("bc", "bcde", 4));
-  EXPECT_EQ(1, strncmp("xyz", "xyy", 10));
-  EXPECT_EQ(1, strncmp("baa", "aaa", 1));
-  EXPECT_EQ(1, strncmp("zyx", "", 2));
-}
-
-static inline char* MallocAndMemsetString(size_t size) {
-  char *s = Ident((char*)malloc(size));
-  memset(s, 'z', size);
-  return s;
+  EXPECT_GT(0, strncmp("abcde", "abcfa", 4));
+  EXPECT_GT(0, strncmp("a", "b", 5));
+  EXPECT_GT(0, strncmp("bc", "bcde", 4));
+  EXPECT_LT(0, strncmp("xyz", "xyy", 10));
+  EXPECT_LT(0, strncmp("baa", "aaa", 1));
+  EXPECT_LT(0, strncmp("zyx", "", 2));
+
+  // strcasecmp
+  EXPECT_EQ(0, strcasecmp("", ""));
+  EXPECT_EQ(0, strcasecmp("zzz", "zzz"));
+  EXPECT_EQ(0, strcasecmp("abCD", "ABcd"));
+  EXPECT_GT(0, strcasecmp("aB", "Ac"));
+  EXPECT_GT(0, strcasecmp("ABC", "ABCd"));
+  EXPECT_LT(0, strcasecmp("acc", "abc"));
+  EXPECT_LT(0, strcasecmp("ABCd", "abc"));
+
+  // strncasecmp
+  EXPECT_EQ(0, strncasecmp("a", "b", 0));
+  EXPECT_EQ(0, strncasecmp("abCD", "ABcd", 10));
+  EXPECT_EQ(0, strncasecmp("abCd", "ABcef", 3));
+  EXPECT_GT(0, strncasecmp("abcde", "ABCfa", 4));
+  EXPECT_GT(0, strncasecmp("a", "B", 5));
+  EXPECT_GT(0, strncasecmp("bc", "BCde", 4));
+  EXPECT_LT(0, strncasecmp("xyz", "xyy", 10));
+  EXPECT_LT(0, strncasecmp("Baa", "aaa", 1));
+  EXPECT_LT(0, strncasecmp("zyx", "", 2));
 }
 
-TEST(AddressSanitizer, StrCmpOOBTest) {
+typedef int(*PointerToStrCmp)(const char*, const char*);
+void RunStrCmpTest(PointerToStrCmp StrCmp) {
   size_t size = Ident(100);
   char *s1 = MallocAndMemsetString(size);
   char *s2 = MallocAndMemsetString(size);
   s1[size - 1] = '\0';
   s2[size - 1] = '\0';
-  // Normal strcmp calls
-  Ident(strcmp(s1, s2));
-  Ident(strcmp(s1, s2 + size - 1));
-  Ident(strcmp(s1 + size - 1, s2 + size - 1));
+  // Normal StrCmp calls
+  Ident(StrCmp(s1, s2));
+  Ident(StrCmp(s1, s2 + size - 1));
+  Ident(StrCmp(s1 + size - 1, s2 + size - 1));
   s1[size - 1] = 'z';
   s2[size - 1] = 'x';
-  Ident(strcmp(s1, s2));
+  Ident(StrCmp(s1, s2));
   // One of arguments points to not allocated memory.
-  EXPECT_DEATH(Ident(strcmp)(s1 - 1, s2), LeftOOBErrorMessage(1));
-  EXPECT_DEATH(Ident(strcmp)(s1, s2 - 1), LeftOOBErrorMessage(1));
-  EXPECT_DEATH(Ident(strcmp)(s1 + size, s2), RightOOBErrorMessage(0));
-  EXPECT_DEATH(Ident(strcmp)(s1, s2 + size), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Ident(StrCmp)(s1 + size, s2), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrCmp)(s1, s2 + size), RightOOBErrorMessage(0));
   // Hit unallocated memory and die.
   s2[size - 1] = 'z';
-  EXPECT_DEATH(Ident(strcmp)(s1, s1), RightOOBErrorMessage(0));
-  EXPECT_DEATH(Ident(strcmp)(s1 + size - 1, s2), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrCmp)(s1, s1), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrCmp)(s1 + size - 1, s2), RightOOBErrorMessage(0));
   free(s1);
   free(s2);
 }
 
-TEST(AddressSanitizer, StrNCmpOOBTest) {
+TEST(AddressSanitizer, StrCmpOOBTest) {
+  RunStrCmpTest(&strcmp);
+}
+
+TEST(AddressSanitizer, StrCaseCmpOOBTest) {
+  RunStrCmpTest(&strcasecmp);
+}
+
+typedef int(*PointerToStrNCmp)(const char*, const char*, size_t);
+void RunStrNCmpTest(PointerToStrNCmp StrNCmp) {
   size_t size = Ident(100);
   char *s1 = MallocAndMemsetString(size);
   char *s2 = MallocAndMemsetString(size);
   s1[size - 1] = '\0';
   s2[size - 1] = '\0';
-  // Normal strncmp calls
-  Ident(strncmp(s1, s2, size + 2));
+  // Normal StrNCmp calls
+  Ident(StrNCmp(s1, s2, size + 2));
   s1[size - 1] = 'z';
   s2[size - 1] = 'x';
-  Ident(strncmp(s1 + size - 2, s2 + size - 2, size));
+  Ident(StrNCmp(s1 + size - 2, s2 + size - 2, size));
   s2[size - 1] = 'z';
-  Ident(strncmp(s1 - 1, s2 - 1, 0));
-  Ident(strncmp(s1 + size - 1, s2 + size - 1, 1));
+  Ident(StrNCmp(s1 - 1, s2 - 1, 0));
+  Ident(StrNCmp(s1 + size - 1, s2 + size - 1, 1));
   // One of arguments points to not allocated memory.
-  EXPECT_DEATH(Ident(strncmp)(s1 - 1, s2, 1), LeftOOBErrorMessage(1));
-  EXPECT_DEATH(Ident(strncmp)(s1, s2 - 1, 1), LeftOOBErrorMessage(1));
-  EXPECT_DEATH(Ident(strncmp)(s1 + size, s2, 1), RightOOBErrorMessage(0));
-  EXPECT_DEATH(Ident(strncmp)(s1, s2 + size, 1), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrNCmp)(s1 - 1, s2, 1), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Ident(StrNCmp)(s1, s2 - 1, 1), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Ident(StrNCmp)(s1 + size, s2, 1), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrNCmp)(s1, s2 + size, 1), RightOOBErrorMessage(0));
   // Hit unallocated memory and die.
-  EXPECT_DEATH(Ident(strncmp)(s1 + 1, s2 + 1, size), RightOOBErrorMessage(0));
-  EXPECT_DEATH(Ident(strncmp)(s1 + size - 1, s2, 2), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrNCmp)(s1 + 1, s2 + 1, size), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Ident(StrNCmp)(s1 + size - 1, s2, 2), RightOOBErrorMessage(0));
   free(s1);
   free(s2);
 }
 
+TEST(AddressSanitizer, StrNCmpOOBTest) {
+  RunStrNCmpTest(&strncmp);
+}
+
+TEST(AddressSanitizer, StrNCaseCmpOOBTest) {
+  RunStrNCmpTest(&strncasecmp);
+}
+
 static const char *kOverlapErrorMessage = "strcpy-param-overlap";
 
 TEST(AddressSanitizer, StrArgsOverlapTest) {





More information about the llvm-commits mailing list