diff options
author | Kamil Rytarowski <n54@gmx.com> | 2018-02-24 01:01:14 +0000 |
---|---|---|
committer | Kamil Rytarowski <n54@gmx.com> | 2018-02-24 01:01:14 +0000 |
commit | c22867f5fc960970d413a15cfe47a2e7379c6e29 (patch) | |
tree | 34028ec596559ce619b2fe9b4097a9eef623b7e5 /compiler-rt/test/sanitizer_common | |
parent | 524946232b38103b0582a4aecf0c64e99843f8bd (diff) | |
download | bcm5719-llvm-c22867f5fc960970d413a15cfe47a2e7379c6e29.tar.gz bcm5719-llvm-c22867f5fc960970d413a15cfe47a2e7379c6e29.zip |
Correct ctype(3) functions with NLS on NetBSD
Summary:
The setlocale(3) function reloads the ctype(3) arrays from
external files. This happens behind the scenes in the internals
of libc (citrus library, runes functions etc).
ctype(3) functions like isspace(3) can be provided with two
variations on NetBSD: inlined or via a global symbol in libc:
```
#if defined(_NETBSD_SOURCE) && !defined(_CTYPE_NOINLINE) && \
!defined(__cplusplus)
#include <sys/ctype_inline.h>
#else
#include <sys/ctype_bits.h>
#endif
```
The in-lined versions are de-facto array lookup operations.
```
#define isspace(c) ((int)((_ctype_tab_ + 1)[(c)] & _CTYPE_S))
```
After setting setlocale(3) the ctype(3) arrays (_ctype_tab_,
_toupper_tab_, _tolower_tab_) are reload behind the scenes
and they are required to be marked as initialized.
Set them initialized inside the common setlocale(3) interceptor.
The arrays are of size of 257 elements: 0..255 + 1 (EOF).
This corrects errors on NetBSD/amd64 in applications
prebuilt with MSan.
Sponsored by <The NetBSD Foundation>
Reviewers: vitalybuka, dvyukov, joerg
Reviewed By: vitalybuka
Subscribers: llvm-commits, kubamracek, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D42020
llvm-svn: 326008
Diffstat (limited to 'compiler-rt/test/sanitizer_common')
-rw-r--r-- | compiler-rt/test/sanitizer_common/TestCases/ctype.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/compiler-rt/test/sanitizer_common/TestCases/ctype.c b/compiler-rt/test/sanitizer_common/TestCases/ctype.c new file mode 100644 index 00000000000..37e0af89be6 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/ctype.c @@ -0,0 +1,89 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <ctype.h> +#include <limits.h> +#include <locale.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +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; +} |