[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