[PATCH] D30384: [asan] Add an interceptor for strtok
Manuel Rigger via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 27 14:57:44 PST 2017
mrigger updated this revision to Diff 89941.
mrigger added a comment.
Herald added a subscriber: kubamracek.
Thanks a lot for your feedback @ygribov! I improved the test case based on it. Additionally, I changed the interceptor to use `ASAN_READ_STRING_OF_LEN` instead of directly calling `ASAN_READ_RANGE`. However, I think I have not yet understood why using `strict_strings` should only verify the string until the first delimiter. If I select the passed `n` to be smaller than `strlen(str) + 1` then the test case fails, since it does not detect the overflow. What did I understand wrong? Should I instead implement the test case in `projects/compiler-rt/test/asan/TestCases/` and set `RUN: %env_asan_opts=strict_string_checks=true`? If yes, should I select `n` to be `strlen(str)` (like the other interceptors) or `1`?
https://reviews.llvm.org/D30384
Files:
lib/asan/asan_interceptors.cc
lib/asan/tests/asan_str_test.cc
Index: lib/asan/tests/asan_str_test.cc
===================================================================
--- lib/asan/tests/asan_str_test.cc
+++ lib/asan/tests/asan_str_test.cc
@@ -107,6 +107,32 @@
free(heap_string);
}
+TEST(AddressSanitizer, StrTokTest) {
+ size_t size = Ident(100);
+ size_t token_delim_size = Ident(3);
+ char *s = MallocAndMemsetString(size, 'a');
+ char *token_delim = MallocAndMemsetString(token_delim_size, 'b');
+ s[size - 1] = '\0';
+ token_delim[token_delim_size - 1] = '\0';
+ // Normal call.
+ strtok(s, token_delim);
+ // Argument points to not-allocated memory.
+ EXPECT_DEATH(Ident(strtok(token_delim - 1, s)),
+ LeftOOBReadMessage(1));
+ EXPECT_DEATH(Ident(strtok(token_delim, s - 1)),
+ LeftOOBReadMessage(1));
+ EXPECT_DEATH(Ident(strtok(token_delim + token_delim_size, s)),
+ RightOOBReadMessage(0));
+ EXPECT_DEATH(Ident(strtok(token_delim, s + size)),
+ RightOOBReadMessage(0));
+ // Cause out-of-bounds read by missing NULL terminator.
+ s[size - 1] = 'z';
+ EXPECT_DEATH(Ident(strtok(token_delim, s)), RightOOBReadMessage(0));
+ free(s);
+ free(token_delim);
+}
+
+
#if SANITIZER_TEST_HAS_STRNLEN
TEST(AddressSanitizer, StrNLenOOBTest) {
size_t size = Ident(123);
Index: lib/asan/asan_interceptors.cc
===================================================================
--- lib/asan/asan_interceptors.cc
+++ lib/asan/asan_interceptors.cc
@@ -538,6 +538,19 @@
return REAL(strcpy)(to, from); // NOLINT
}
+INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strtok);
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr del_length = REAL(strlen)(delimiters);
+ uptr str_length = REAL(strlen)(str);
+ ASAN_READ_STRING_OF_LEN(ctx, delimiters, del_length, del_length + 1);
+ ASAN_READ_STRING_OF_LEN(ctx, str, str_length, str_length + 1);
+ }
+ return REAL(strtok)(str, delimiters);
+}
+
INTERCEPTOR(char*, strdup, const char *s) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
@@ -716,6 +729,7 @@
ASAN_INTERCEPT_FUNC(strcat); // NOLINT
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
ASAN_INTERCEPT_FUNC(wcslen);
+ ASAN_INTERCEPT_FUNC(strtok);
ASAN_INTERCEPT_FUNC(strncat);
ASAN_INTERCEPT_FUNC(strncpy);
ASAN_INTERCEPT_FUNC(strdup);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30384.89941.patch
Type: text/x-patch
Size: 2322 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170227/67f5bf51/attachment.bin>
More information about the llvm-commits
mailing list