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

Alexey Samsonov samsonov at google.com
Thu Mar 29 01:04:35 PDT 2012


Author: samsonov
Date: Thu Mar 29 03:04:35 2012
New Revision: 153637

URL: http://llvm.org/viewvc/llvm-project?rev=153637&view=rev
Log:
[ASan] interceptors for atoi/atol/atoll

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=153637&r1=153636&r2=153637&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Thu Mar 29 03:04:35 2012
@@ -27,9 +27,9 @@
 // Use macro to describe if specific function should be
 // intercepted on a given platform.
 #if !defined(_WIN32)
-# define ASAN_INTERCEPT_STRTOLL 1
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
 #else
-# define ASAN_INTERCEPT_STRTOLL 0
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
 #endif
 
 #if !defined(__APPLE__)
@@ -89,8 +89,11 @@
 # endif
 
 // stdlib.h
+int atoi(const char *nptr);
+long atol(const char *nptr);  // NOLINT
 long strtol(const char *nptr, char **endptr, int base);  // NOLINT
-# if ASAN_INTERCEPT_STRTOLL
+# if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+long long atoll(const char *nptr);  // NOLINT
 long long strtoll(const char *nptr, char **endptr, int base);  // NOLINT
 # endif
 
@@ -677,40 +680,67 @@
   CHECK(*endptr >= nptr);
 }
 
-# if ASAN_INTERCEPT_STRTOLL
-INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
+INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
             char **endptr, int base) {
   ENSURE_ASAN_INITED();
   if (!FLAG_replace_str) {
-    return REAL(strtoll)(nptr, endptr, base);
+    return REAL(strtol)(nptr, endptr, base);
   }
   char *real_endptr;
-  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
+  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
   if (endptr != NULL) {
     *endptr = real_endptr;
   }
-  // If base has unsupported value, strtoll can exit with EINVAL
-  // without reading any characters. So do additional checks only
-  // if base is valid.
   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
+INTERCEPTOR(int, atoi, const char *nptr) {
+  ENSURE_ASAN_INITED();
+  if (!FLAG_replace_str) {
+    return REAL(atoi)(nptr);
+  }
+  char *real_endptr;
+  // "man atoi" tells that behavior of atoi(nptr) is the same as
+  // strtol(nptr, NULL, 10), i.e. it sets errno to ERANGE if the
+  // parsed integer can't be stored in *long* type (even if it's
+  // different from int). So, we just imitate this behavior.
+  int result = REAL(strtol)(nptr, &real_endptr, 10);
+  FixRealStrtolEndptr(nptr, &real_endptr);
+  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+  return result;
+}
+
+INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
+  ENSURE_ASAN_INITED();
+  if (!FLAG_replace_str) {
+    return REAL(atol)(nptr);
+  }
+  char *real_endptr;
+  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
+  FixRealStrtolEndptr(nptr, &real_endptr);
+  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+  return result;
+}
+
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
             char **endptr, int base) {
   ENSURE_ASAN_INITED();
   if (!FLAG_replace_str) {
-    return REAL(strtol)(nptr, endptr, base);
+    return REAL(strtoll)(nptr, endptr, base);
   }
   char *real_endptr;
-  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
+  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
   if (endptr != NULL) {
     *endptr = real_endptr;
   }
+  // If base has unsupported value, strtoll can exit with EINVAL
+  // without reading any characters. So do additional checks only
+  // if base is valid.
   if (IsValidStrtolBase(base)) {
     FixRealStrtolEndptr(nptr, &real_endptr);
     ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
@@ -718,6 +748,19 @@
   return result;
 }
 
+INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
+  ENSURE_ASAN_INITED();
+  if (!FLAG_replace_str) {
+    return REAL(atoll)(nptr);
+  }
+  char *real_endptr;
+  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
+  FixRealStrtolEndptr(nptr, &real_endptr);
+  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+  return result;
+}
+#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+
 #if defined(_WIN32)
 INTERCEPTOR_WINAPI(DWORD, CreateThread,
                    void* security, size_t stack_size,
@@ -777,8 +820,11 @@
   CHECK(INTERCEPT_FUNCTION(strnlen));
 #endif
 
+  CHECK(INTERCEPT_FUNCTION(atoi));
+  CHECK(INTERCEPT_FUNCTION(atol));
   CHECK(INTERCEPT_FUNCTION(strtol));
-#if ASAN_INTERCEPT_STRTOLL
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+  CHECK(INTERCEPT_FUNCTION(atoll));
   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=153637&r1=153636&r2=153637&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Thu Mar 29 03:04:35 2012
@@ -986,11 +986,14 @@
   free(heap_string);
 }
 
-static inline char* MallocAndMemsetString(size_t size) {
+static inline char* MallocAndMemsetString(size_t size, char ch) {
   char *s = Ident((char*)malloc(size));
-  memset(s, 'z', size);
+  memset(s, ch, size);
   return s;
 }
+static inline char* MallocAndMemsetString(size_t size) {
+  return MallocAndMemsetString(size, 'z');
+}
 
 #ifndef __APPLE__
 TEST(AddressSanitizer, StrNLenOOBTest) {
@@ -1349,6 +1352,47 @@
   free(str);
 }
 
+void CallAtoi(const char *nptr) {
+  Ident(atoi(nptr));
+}
+void CallAtol(const char *nptr) {
+  Ident(atol(nptr));
+}
+void CallAtoll(const char *nptr) {
+  Ident(atoll(nptr));
+}
+typedef void(*PointerToCallAtoi)(const char*);
+
+void RunAtoiOOBTest(PointerToCallAtoi Atoi) {
+  char *array = MallocAndMemsetString(10, '1');
+  // Invalid pointer to the string.
+  EXPECT_DEATH(Atoi(array + 11), RightOOBErrorMessage(1));
+  EXPECT_DEATH(Atoi(array - 1), LeftOOBErrorMessage(1));
+  // Die if a buffer doesn't have terminating NULL.
+  EXPECT_DEATH(Atoi(array), RightOOBErrorMessage(0));
+  // Make last symbol a terminating NULL or other non-digit.
+  array[9] = '\0';
+  Atoi(array);
+  array[9] = 'a';
+  Atoi(array);
+  Atoi(array + 9);
+  // Sometimes we need to detect overflow if no digits are found.
+  memset(array, ' ', 10);
+  EXPECT_DEATH(Atoi(array), RightOOBErrorMessage(0));
+  array[9] = '-';
+  EXPECT_DEATH(Atoi(array), RightOOBErrorMessage(0));
+  EXPECT_DEATH(Atoi(array + 9), RightOOBErrorMessage(0));
+  array[8] = '-';
+  Atoi(array);
+  delete array;
+}
+
+TEST(AddressSanitizer, AtoiAndFriendsOOBTest) {
+  RunAtoiOOBTest(&CallAtoi);
+  RunAtoiOOBTest(&CallAtol);
+  RunAtoiOOBTest(&CallAtoll);
+}
+
 void CallStrtol(const char *nptr, char **endptr, int base) {
   Ident(strtol(nptr, endptr, base));
 }





More information about the llvm-commits mailing list