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

Alexey Samsonov samsonov at google.com
Mon Mar 26 09:42:23 PDT 2012


Author: samsonov
Date: Mon Mar 26 11:42:22 2012
New Revision: 153444

URL: http://llvm.org/viewvc/llvm-project?rev=153444&view=rev
Log:
[ASan] add interceptor for strtol

Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.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=153444&r1=153443&r2=153444&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Mon Mar 26 11:42:22 2012
@@ -89,6 +89,7 @@
 # endif
 
 // stdlib.h
+long strtol(const char *nptr, char **endptr, int base);  // NOLINT
 # if ASAN_INTERCEPT_STRTOLL
 long long strtoll(const char *nptr, char **endptr, int base);  // NOLINT
 # endif
@@ -659,15 +660,24 @@
 }
 #endif  // ASAN_INTERCEPT_STRNLEN
 
-# if ASAN_INTERCEPT_STRTOLL
-// Returns pointer to first character of "nptr" after skipping
-// leading blanks and optional +/- sign.
-static char *SkipBlanksAndSign(const char *nptr) {
-  while (IsSpace(*nptr)) nptr++;
-  if (*nptr == '+' || *nptr == '-') nptr++;
-  return (char*)nptr;
+static inline bool IsValidStrtolBase(int base) {
+  return (base == 0) || (2 <= base && base <= 36);
+}
+
+static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
+  CHECK(endptr != NULL);
+  if (nptr == *endptr) {
+    // No digits were found at strtol call, we need to find out the last
+    // symbol accessed by strtoll on our own.
+    // We get this symbol by skipping leading blanks and optional +/- sign.
+    while (IsSpace(*nptr)) nptr++;
+    if (*nptr == '+' || *nptr == '-') nptr++;
+    *endptr = (char*)nptr;
+  }
+  CHECK(*endptr >= nptr);
 }
 
+# if ASAN_INTERCEPT_STRTOLL
 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
             char **endptr, int base) {
   ENSURE_ASAN_INITED();
@@ -682,19 +692,32 @@
   // If base has unsupported value, strtoll can exit with EINVAL
   // without reading any characters. So do additional checks only
   // if base is valid.
-  if (base == 0 || (2 <= base && base <= 36)) {
-    if (real_endptr == nptr) {
-      // No digits were found, find out the last symbol read by strtoll
-      // on our own.
-      real_endptr = SkipBlanksAndSign(nptr);
-    }
-    CHECK(real_endptr >= nptr);
+  if (IsValidStrtolBase(base)) {
+    FixRealStrtolEndptr(nptr, &real_endptr);
     ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
   }
   return result;
 }
 #endif  // ASAN_INTERCEPT_STRTOLL
 
+INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
+            char **endptr, int base) {
+  ENSURE_ASAN_INITED();
+  if (!FLAG_replace_str) {
+    return REAL(strtol)(nptr, endptr, base);
+  }
+  char *real_endptr;
+  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
+  if (endptr != NULL) {
+    *endptr = real_endptr;
+  }
+  if (IsValidStrtolBase(base)) {
+    FixRealStrtolEndptr(nptr, &real_endptr);
+    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+  }
+  return result;
+}
+
 #if defined(_WIN32)
 INTERCEPTOR_WINAPI(DWORD, CreateThread,
                    void* security, size_t stack_size,
@@ -754,6 +777,7 @@
   CHECK(INTERCEPT_FUNCTION(strnlen));
 #endif
 
+  CHECK(INTERCEPT_FUNCTION(strtol));
 #if ASAN_INTERCEPT_STRTOLL
   CHECK(INTERCEPT_FUNCTION(strtoll));
 #endif

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=153444&r1=153443&r2=153444&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Mon Mar 26 11:42:22 2012
@@ -1349,46 +1349,61 @@
   free(str);
 }
 
-TEST(AddressSanitizer, StrtollOOBTest) {
+void CallStrtol(const char *nptr, char **endptr, int base) {
+  Ident(strtol(nptr, endptr, base));
+}
+void CallStrtoll(const char *nptr, char **endptr, int base) {
+  Ident(strtoll(nptr, endptr, base));
+}
+typedef void(*PointerToCallStrtol)(const char*, char**, int);
+
+void RunStrtolOOBTest(PointerToCallStrtol Strtol) {
   char *array = MallocAndMemsetString(3);
   char *endptr = NULL;
   array[0] = '1';
   array[1] = '2';
   array[2] = '3';
   // Invalid pointer to the string.
-  EXPECT_DEATH(strtoll(array + 3, NULL, 0), RightOOBErrorMessage(0));
-  EXPECT_DEATH(strtoll(array - 1, NULL, 0), LeftOOBErrorMessage(1));
+  EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBErrorMessage(1));
   // Buffer overflow if there is no terminating null (depends on base).
-  Ident(strtoll(array, &endptr, 3));
+  Strtol(array, &endptr, 3);
   EXPECT_EQ(array + 2, endptr);
-  EXPECT_DEATH(strtoll(array, NULL, 0), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBErrorMessage(0));
   array[2] = 'z';
-  Ident(strtoll(array, &endptr, 35));
+  Strtol(array, &endptr, 35);
   EXPECT_EQ(array + 2, endptr);
-  EXPECT_DEATH(strtoll(array, NULL, 36), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBErrorMessage(0));
   // Add terminating zero to get rid of overflow.
   array[2] = '\0';
-  Ident(strtoll(array, NULL, 36));
+  Strtol(array, NULL, 36);
   // Don't check for overflow if base is invalid.
-  Ident(strtoll(array - 1, NULL, -1));
-  Ident(strtoll(array + 3, NULL, 1));
+  Strtol(array - 1, NULL, -1);
+  Strtol(array + 3, NULL, 1);
   // Sometimes we need to detect overflow if no digits are found.
   array[0] = array[1] = array[2] = ' ';
-  EXPECT_DEATH(strtoll(array, NULL, 0), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBErrorMessage(0));
   array[2] = '+';
-  EXPECT_DEATH(strtoll(array, NULL, 0), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBErrorMessage(0));
   array[2] = '-';
-  EXPECT_DEATH(strtoll(array, NULL, 0), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBErrorMessage(0));
   array[1] = '+';
-  Ident(strtoll(array, NULL, 0));
+  Strtol(array, NULL, 0);
   array[1] = array[2] = 'z';
-  Ident(strtoll(array, &endptr, 0));
+  Strtol(array, &endptr, 0);
   EXPECT_EQ(array, endptr);
-  Ident(strtoll(array + 2, NULL, 0));
+  Strtol(array + 2, NULL, 0);
   EXPECT_EQ(array, endptr);
   delete array;
 }
 
+TEST(AddressSanitizer, StrtollOOBTest) {
+  RunStrtolOOBTest(&CallStrtoll);
+}
+TEST(AddressSanitizer, StrtolOOBTest) {
+  RunStrtolOOBTest(&CallStrtol);
+}
+
 // At the moment we instrument memcpy/memove/memset calls at compile time so we
 // can't handle OOB error if these functions are called by pointer, see disabled
 // MemIntrinsicCallByPointerTest below





More information about the llvm-commits mailing list