summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2012-06-08 13:27:46 +0000
committerAlexey Samsonov <samsonov@google.com>2012-06-08 13:27:46 +0000
commitc1bdd5adca453f2fae238a4c53ade35ae60b85da (patch)
tree0e80fb9a6fe604cd80c5b6ac7536f7daa51d4a4e /lib
parentf7667cc84cdd8923c0b6c7cfc92b7bd5692ce18c (diff)
downloadcompiler-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.cc18
-rw-r--r--lib/asan/tests/asan_test.cc53
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);
}