Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -110,6 +110,9 @@ #define times __times13 #define wait3 __wait350 #define wait4 __wait450 +extern const unsigned short *_ctype_tab_; +extern const short *_toupper_tab_; +extern const short *_tolower_tab_; #endif // Platform-specific options. @@ -3186,13 +3189,25 @@ #endif #if SANITIZER_INTERCEPT_SETLOCALE +static void unpoison_ctype_arrays(void *ctx) { +#if SANITIZER_NETBSD + // These arrays contain 256 regular elements in unsigned char range + 1 EOF + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short)); +#endif +} + INTERCEPTOR(char *, setlocale, int category, char *locale) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale); if (locale) COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1); char *res = REAL(setlocale)(category, locale); - if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + if (res) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + unpoison_ctype_arrays(ctx); + } return res; } Index: test/sanitizer_common/TestCases/ctype.c =================================================================== --- test/sanitizer_common/TestCases/ctype.c +++ test/sanitizer_common/TestCases/ctype.c @@ -0,0 +1,89 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include +#include + +void check_ctype(void) { + unsigned char c; + volatile size_t i = 0; /* a dummy variable to prevent optimizing code out */ + + for (c = 0; c < UCHAR_MAX; c++) + i += !!isalpha(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isascii(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isblank(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!iscntrl(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isdigit(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isgraph(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!islower(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isprint(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!ispunct(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isspace(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isupper(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isxdigit(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isalnum(c); + + for (c = 0; c < UCHAR_MAX; c++) + i += !!tolower(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!toupper(c); + + i += !!isalpha(EOF); + i += !!isascii(EOF); + i += !!isblank(EOF); + i += !!iscntrl(EOF); + i += !!isdigit(EOF); + i += !!isgraph(EOF); + i += !!islower(EOF); + i += !!isprint(EOF); + i += !!ispunct(EOF); + i += !!isspace(EOF); + i += !!isupper(EOF); + i += !!isxdigit(EOF); + i += !!isalnum(EOF); + + i += !!tolower(EOF); + i += !!toupper(EOF); + + if (i) + return; + else + return; +} + +int main(int argc, char **argv) { + check_ctype(); + + setlocale(LC_ALL, ""); + + check_ctype(); + + setlocale(LC_ALL, "en_US.UTF-8"); + + check_ctype(); + + setlocale(LC_CTYPE, "pl_PL.UTF-8"); + + check_ctype(); + + printf("OK\n"); + + // CHECK: OK + + return 0; +}