Index: lib/asan/asan_interceptors.h =================================================================== --- lib/asan/asan_interceptors.h +++ lib/asan/asan_interceptors.h @@ -40,12 +40,6 @@ # define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0 #endif -#if !SANITIZER_MAC -# define ASAN_INTERCEPT_STRNLEN 1 -#else -# define ASAN_INTERCEPT_STRNLEN 0 -#endif - #if SANITIZER_LINUX && !SANITIZER_ANDROID # define ASAN_INTERCEPT_SWAPCONTEXT 1 #else Index: lib/asan/asan_interceptors.cc =================================================================== --- lib/asan/asan_interceptors.cc +++ lib/asan/asan_interceptors.cc @@ -111,7 +111,7 @@ } while (0) static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { -#if ASAN_INTERCEPT_STRNLEN +#if SANITIZER_INTERCEPT_STRNLEN if (REAL(strnlen)) { return REAL(strnlen)(s, maxlen); } @@ -583,19 +583,6 @@ return REAL(strncpy)(to, from, size); } -#if ASAN_INTERCEPT_STRNLEN -INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { - void *ctx; - ASAN_INTERCEPTOR_ENTER(ctx, strnlen); - ENSURE_ASAN_INITED(); - uptr length = REAL(strnlen)(s, maxlen); - if (flags()->replace_str) { - ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen)); - } - return length; -} -#endif // ASAN_INTERCEPT_STRNLEN - INTERCEPTOR(long, strtol, const char *nptr, // NOLINT char **endptr, int base) { void *ctx; @@ -728,9 +715,6 @@ ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncpy); ASAN_INTERCEPT_FUNC(strdup); -#if ASAN_INTERCEPT_STRNLEN - ASAN_INTERCEPT_FUNC(strnlen); -#endif #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX ASAN_INTERCEPT_FUNC(index); #endif Index: lib/msan/msan_interceptors.cc =================================================================== --- lib/msan/msan_interceptors.cc +++ lib/msan/msan_interceptors.cc @@ -44,6 +44,7 @@ using __sanitizer::atomic_uintptr_t; DECLARE_REAL(SIZE_T, strlen, const char *s) +DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen) #if SANITIZER_FREEBSD #define __errno_location __error @@ -282,14 +283,6 @@ #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS #endif -INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) { - ENSURE_MSAN_INITED(); - SIZE_T res = REAL(strnlen)(s, n); - SIZE_T scan_size = (res == n) ? res : res + 1; - CHECK_UNPOISONED(s, scan_size); - return res; -} - INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT ENSURE_MSAN_INITED(); GET_STORE_STACK_TRACE; @@ -1555,7 +1548,6 @@ INTERCEPT_FUNCTION(strndup); MSAN_MAYBE_INTERCEPT___STRNDUP; INTERCEPT_FUNCTION(strncpy); // NOLINT - INTERCEPT_FUNCTION(strnlen); INTERCEPT_FUNCTION(gcvt); INTERCEPT_FUNCTION(strcat); // NOLINT INTERCEPT_FUNCTION(strncat); // NOLINT Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -218,6 +218,20 @@ #define INIT_STRLEN #endif +#if SANITIZER_INTERCEPT_STRNLEN +INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen); + SIZE_T length = REAL(strnlen)(s, maxlen); + if (common_flags()->intercept_strlen) + COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen)); + return length; +} +#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen) +#else +#define INIT_STRNLEN +#endif + #if SANITIZER_INTERCEPT_TEXTDOMAIN INTERCEPTOR(char*, textdomain, const char *domainname) { void *ctx; @@ -5445,6 +5459,7 @@ INIT_TEXTDOMAIN; INIT_STRLEN; + INIT_STRNLEN; INIT_STRCMP; INIT_STRNCMP; INIT_STRCASECMP; Index: lib/sanitizer_common/sanitizer_flags.inc =================================================================== --- lib/sanitizer_common/sanitizer_flags.inc +++ lib/sanitizer_common/sanitizer_flags.inc @@ -183,7 +183,7 @@ "If set, uses custom wrappers for strpbrk function " "to find more errors.") COMMON_FLAG(bool, intercept_strlen, true, - "If set, uses custom wrappers for strlen function " + "If set, uses custom wrappers for strlen and strnlen functions " "to find more errors.") COMMON_FLAG(bool, intercept_strchr, true, "If set, uses custom wrappers for strchr, strchrnul, and strrchr " Index: lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_interceptors.h +++ lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -43,8 +43,10 @@ #if SANITIZER_MAC # define SI_MAC 1 +# define SI_NOT_MAC 0 #else # define SI_MAC 0 +# define SI_NOT_MAC 1 #endif #if SANITIZER_IOS @@ -60,6 +62,7 @@ #endif #define SANITIZER_INTERCEPT_STRLEN 1 +#define SANITIZER_INTERCEPT_STRNLEN SI_NOT_MAC #define SANITIZER_INTERCEPT_STRCMP 1 #define SANITIZER_INTERCEPT_STRSTR 1 #define SANITIZER_INTERCEPT_STRCASESTR SI_NOT_WINDOWS Index: test/sanitizer_common/TestCases/strnlen.c =================================================================== --- /dev/null +++ test/sanitizer_common/TestCases/strnlen.c @@ -0,0 +1,12 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +#include +#include +int main(int argc, char **argv) { + const char *s = "mytest"; + assert(strnlen(s, 0) == 0UL); + assert(strnlen(s, 1) == 1UL); + assert(strnlen(s, 6) == strlen(s)); + assert(strnlen(s, 7) == strlen(s)); + return 0; +}