Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -6724,6 +6724,40 @@ #define INIT_OPEN_BY_HANDLE_AT #endif +#if SANITIZER_INTERCEPT_STRLCPY +INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) { + void *ctx; + SIZE_T res; + COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size); + if (src) { + SIZE_T len = REAL(strnlen)(src, size); + COMMON_INTERCEPTOR_READ_STRING(ctx, src, Min(len, size - 1) + 1); + } + res = REAL(strlcpy)(dst, src, size); + COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1); + return res; +} + +INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size); + // src is checked in the strlcpy() interceptor + if (dst) { + SIZE_T len = REAL(strnlen)(dst, size); + COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1); + // Reuse the rest of the code in the strlcpy() interceptor + dst += len; + size -= len; + } + return WRAP(strlcpy)(dst, src, size); +} +#define INIT_STRLCPY \ + COMMON_INTERCEPT_FUNCTION(strlcpy); \ + COMMON_INTERCEPT_FUNCTION(strlcat); +#else +#define INIT_STRLCPY +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -6946,9 +6980,9 @@ INIT_GETGROUPLIST; INIT_READLINK; INIT_READLINKAT; - INIT_NAME_TO_HANDLE_AT; INIT_OPEN_BY_HANDLE_AT; + INIT_STRLCPY; #if SANITIZER_NETBSD COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock); Index: lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_interceptors.h +++ lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -441,6 +441,7 @@ #define SANITIZER_INTERCEPT_ACCESS SI_NETBSD #define SANITIZER_INTERCEPT_FACCESSAT SI_NETBSD #define SANITIZER_INTERCEPT_GETGROUPLIST SI_NETBSD +#define SANITIZER_INTERCEPT_STRLCPY SI_NETBSD #define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX_NOT_ANDROID Index: test/sanitizer_common/TestCases/NetBSD/strlcat.cc =================================================================== --- /dev/null +++ test/sanitizer_common/TestCases/NetBSD/strlcat.cc @@ -0,0 +1,56 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include +#include +#include + +void +test1() { + const char src[] = "abc"; + char dst[7] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void +test2() { + const char src[] = "abc"; + char dst[7] = {0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void +test3() { + const char src[] = "abc"; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void +test4() { + const char src[] = ""; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu\n", dst, len); +} + +int main(void) { + test1(); + test2(); + test3(); + test4(); + + // CHECK: xyzabc 6 abc 3 xyz 3 xyz 3 + + return 0; +} Index: test/sanitizer_common/TestCases/NetBSD/strlcpy.cc =================================================================== --- /dev/null +++ test/sanitizer_common/TestCases/NetBSD/strlcpy.cc @@ -0,0 +1,56 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include +#include +#include + +void +test1() { + const char src[] = "abc"; + char dst[7] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcpy(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void +test2() { + const char src[] = "abc"; + char dst[7] = {0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void +test3() { + const char src[] = "abc"; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void +test4() { + const char src[] = ""; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu\n", dst, len); +} + +int main(void) { + test1(); + test2(); + test3(); + test4(); + + // CHECK: abc 3 abc 3 xyz 3 0 + + return 0; +}