diff options
author | Alexey Samsonov <samsonov@google.com> | 2012-06-08 13:27:46 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2012-06-08 13:27:46 +0000 |
commit | c1bdd5adca453f2fae238a4c53ade35ae60b85da (patch) | |
tree | 0e80fb9a6fe604cd80c5b6ac7536f7daa51d4a4e /lib | |
parent | f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18c (diff) | |
download | compiler-rt-c1bdd5adca453f2fae238a4c53ade35ae60b85da.tar.gz |
[ASan] add interceptor for strncat
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@158198 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_interceptors.cc | 18 | ||||
-rw-r--r-- | lib/asan/tests/asan_test.cc | 53 |
2 files changed, 71 insertions, 0 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index f6b6754ca..22f6c3101 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -71,6 +71,7 @@ char* strchr(const char *str, int c); char* index(const char *string, int c); # endif char* strcat(char *to, const char* from); // NOLINT +char *strncat(char *to, const char* from, uptr size); char* strcpy(char *to, const char* from); // NOLINT char* strncpy(char *to, const char* from, uptr size); int strcmp(const char *s1, const char* s2); @@ -504,6 +505,22 @@ INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT return REAL(strcat)(to, from); // NOLINT } +INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { + ENSURE_ASAN_INITED(); + if (FLAG_replace_str && size > 0) { + uptr from_length = internal_strnlen(from, size); + ASAN_READ_RANGE(from, Min(size, from_length + 1)); + uptr to_length = REAL(strlen)(to); + ASAN_READ_RANGE(to, to_length); + ASAN_WRITE_RANGE(to + to_length, from_length + 1); + if (from_length > 0) { + CHECK_RANGES_OVERLAP("strncat", to, to_length + 1, + from, Min(size, from_length + 1)); + } + } + return REAL(strncat)(to, from, size); +} + INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { if (!asan_inited) { return internal_strcmp(s1, s2); @@ -759,6 +776,7 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(strcmp); ASAN_INTERCEPT_FUNC(strcpy); // NOLINT ASAN_INTERCEPT_FUNC(strlen); + ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncmp); ASAN_INTERCEPT_FUNC(strncpy); #if !defined(_WIN32) diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc index 9f8af40aa..3646a278e 100644 --- a/lib/asan/tests/asan_test.cc +++ b/lib/asan/tests/asan_test.cc @@ -1252,6 +1252,47 @@ TEST(AddressSanitizer, StrCatOOBTest) { EXPECT_DEATH(strcat(to, from), RightOOBErrorMessage(0)); // length of "to" is just enough. strcat(to, from + 1); + + free(to); + free(from); +} + +TEST(AddressSanitizer, StrNCatOOBTest) { + size_t to_size = Ident(100); + char *to = MallocAndMemsetString(to_size); + to[0] = '\0'; + size_t from_size = Ident(20); + char *from = MallocAndMemsetString(from_size); + // Normal strncat calls. + strncat(to, from, 0); + strncat(to, from, from_size); + from[from_size - 1] = '\0'; + strncat(to, from, 2 * from_size); + // Catenating empty string is not an error. + strncat(to - 1, from, 0); + strncat(to, from + from_size - 1, 10); + // One of arguments points to not allocated memory. + EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBErrorMessage(1)); + EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBErrorMessage(1)); + EXPECT_DEATH(strncat(to + to_size, from, 2), RightOOBErrorMessage(0)); + EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBErrorMessage(0)); + + memset(from, 'z', from_size); + memset(to, 'z', to_size); + to[0] = '\0'; + // "from" is too short. + EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBErrorMessage(0)); + // "to" is not zero-terminated. + EXPECT_DEATH(strncat(to + 1, from, 1), RightOOBErrorMessage(0)); + // "to" is too short to fit "from". + to[0] = 'z'; + to[to_size - from_size + 1] = '\0'; + EXPECT_DEATH(strncat(to, from, from_size - 1), RightOOBErrorMessage(0)); + // "to" is just enough. + strncat(to, from, from_size - 2); + + free(to); + free(from); } static string OverlapErrorMessage(const string &func) { @@ -1308,6 +1349,18 @@ TEST(AddressSanitizer, StrArgsOverlapTest) { EXPECT_DEATH(strcat(str + 9, str), OverlapErrorMessage("strcat")); EXPECT_DEATH(strcat(str + 10, str), OverlapErrorMessage("strcat")); + // Check "strncat". + memset(str, 'z', size); + str[10] = '\0'; + strncat(str, str + 10, 10); // from is empty + strncat(str, str + 11, 10); + str[10] = '\0'; + str[20] = '\0'; + strncat(str + 5, str, 5); + str[10] = '\0'; + EXPECT_DEATH(strncat(str + 5, str, 6), OverlapErrorMessage("strncat")); + EXPECT_DEATH(strncat(str, str + 9, 10), OverlapErrorMessage("strncat")); + free(str); } |