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); 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);