Index: compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -876,6 +876,51 @@ #define INIT_MEMSET #endif +#if SANITIZER_INTERCEPT_MEMSET_PATTERN +INTERCEPTOR(void, memset_pattern4, void *s, const void *p, SIZE_T n) { + void *ctx; + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { + internal_memset_pattern4(s, p, n); + return; + } + COMMON_INTERCEPTOR_ENTER(ctx, memset_pattern4, s, p, n); + if (common_flags()->intercept_intrin) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, n); + REAL(memset_pattern4)(s, p, n); +} + +INTERCEPTOR(void, memset_pattern8, void *s, const void *p, SIZE_T n) { + void *ctx; + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { + internal_memset_pattern8(s, p, n); + return; + } + COMMON_INTERCEPTOR_ENTER(ctx, memset_pattern8, s, p, n); + if (common_flags()->intercept_intrin) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, n); + REAL(memset_pattern8)(s, p, n); +} + +INTERCEPTOR(void, memset_pattern16, void *s, const void *p, SIZE_T n) { + void *ctx; + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { + internal_memset_pattern16(s, p, n); + return; + } + COMMON_INTERCEPTOR_ENTER(ctx, memset_pattern16, s, p, n); + if (common_flags()->intercept_intrin) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, n); + REAL(memset_pattern16)(s, p, n); +} + +#define INIT_MEMSET_PATTERN \ + COMMON_INTERCEPT_FUNCTION(memset_pattern4) \ + COMMON_INTERCEPT_FUNCTION(memset_pattern8) \ + COMMON_INTERCEPT_FUNCTION(memset_pattern16) +#else +#define INIT_MEMSET_PATTERN +#endif + #if SANITIZER_INTERCEPT_MEMMOVE INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) { void *ctx; @@ -10491,6 +10536,7 @@ INIT_MEMMOVE; INIT_MEMCPY; INIT_MEMCHR; + INIT_MEMSET_PATTERN; INIT_MEMCMP; INIT_BCMP; INIT_MEMRCHR; Index: compiler-rt/lib/sanitizer_common/sanitizer_libc.h =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_libc.h +++ compiler-rt/lib/sanitizer_common/sanitizer_libc.h @@ -33,6 +33,9 @@ void *internal_memmove(void *dest, const void *src, uptr n); // Should not be used in performance-critical places. void *internal_memset(void *s, int c, uptr n); +void internal_memset_pattern4(void *s, const void *p, uptr n); +void internal_memset_pattern8(void *s, const void *p, uptr n); +void internal_memset_pattern16(void *s, const void *p, uptr n); char* internal_strchr(const char *s, int c); char *internal_strchrnul(const char *s, int c); int internal_strcmp(const char *s1, const char *s2); Index: compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp @@ -96,6 +96,35 @@ return s; } +// using internal_memmove, thus +// using those in slow code paths +template +static void internal_memset_pattern(void *src, const void *pattern, uptr n) { + char *s = (char*)src; + char *end = s + n; + char *o = s; + + while (end - o >= chunk) { + internal_memmove(o, pattern, chunk); + o += chunk; + } + + if (end - o != 0) + internal_memmove(o, pattern, end - o); +} + +void internal_memset_pattern4(void *s, const void *pattern, uptr n) { + internal_memset_pattern<4>(s, pattern, n); +} + +void internal_memset_pattern8(void *s, const void *pattern, uptr n) { + internal_memset_pattern<8>(s, pattern, n); +} + +void internal_memset_pattern16(void *s, const void *pattern, uptr n) { + internal_memset_pattern<16>(s, pattern, n); +} + uptr internal_strcspn(const char *s, const char *reject) { uptr i; for (i = 0; s[i]; i++) { Index: compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -158,6 +158,7 @@ #define SANITIZER_INTERCEPT_BCMP \ SANITIZER_INTERCEPT_MEMCMP && \ ((SI_POSIX && _GNU_SOURCE) || SI_NETBSD || SI_FREEBSD) +#define SANITIZER_INTERCEPT_MEMSET_PATTERN SI_MAC #define SANITIZER_INTERCEPT_STRNDUP SI_POSIX #define SANITIZER_INTERCEPT___STRNDUP SI_GLIBC #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ Index: compiler-rt/test/sanitizer_common/TestCases/Darwin/memset_pattern.cpp =================================================================== --- /dev/null +++ compiler-rt/test/sanitizer_common/TestCases/Darwin/memset_pattern.cpp @@ -0,0 +1,18 @@ +// RUN: %clangxx -g %s -o %t +#include +#include + +int main(void) { + char s[16]; + memset_pattern4(s, "abc", sizeof(s)); + + printf("%s\n", s); + memset_pattern4(s, "abcd", sizeof(s)); + s[15] = 0; + printf("%s\n", s); +// CHECK: abc +// CHECK: abcdabcdabcdabcd + return 0; +} + +