summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2012-03-29 08:04:35 +0000
committerAlexey Samsonov <samsonov@google.com>2012-03-29 08:04:35 +0000
commitb33c87bbb9056305b57aeed7dd1df43f8c4d085e (patch)
tree1ef3e23de9ce244868e58f4615895324ef3ba8ce /compiler-rt
parenta0a603e5823b6a7534033ba550ff7377ddeb46b9 (diff)
downloadbcm5719-llvm-b33c87bbb9056305b57aeed7dd1df43f8c4d085e.tar.gz
bcm5719-llvm-b33c87bbb9056305b57aeed7dd1df43f8c4d085e.zip
[ASan] interceptors for atoi/atol/atoll
llvm-svn: 153637
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cc76
-rw-r--r--compiler-rt/lib/asan/tests/asan_test.cc48
2 files changed, 107 insertions, 17 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc
index 8228121374a..a11601994e4 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cc
+++ b/compiler-rt/lib/asan/asan_interceptors.cc
@@ -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 @@ size_t strnlen(const char *s, size_t maxlen);
# 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 @@ static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
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 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
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 @@ void InitializeAsanInterceptors() {
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
diff --git a/compiler-rt/lib/asan/tests/asan_test.cc b/compiler-rt/lib/asan/tests/asan_test.cc
index b611d52c744..0dfffb21211 100644
--- a/compiler-rt/lib/asan/tests/asan_test.cc
+++ b/compiler-rt/lib/asan/tests/asan_test.cc
@@ -986,11 +986,14 @@ TEST(AddressSanitizer, StrLenOOBTest) {
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 @@ TEST(AddressSanitizer, StrArgsOverlapTest) {
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));
}
OpenPOWER on IntegriCloud