diff options
Diffstat (limited to 'clang/test/Analysis/string.c')
| -rw-r--r-- | clang/test/Analysis/string.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c index e017aff3b4a1..cdd36275568e 100644 --- a/clang/test/Analysis/string.c +++ b/clang/test/Analysis/string.c @@ -1789,3 +1789,107 @@ void CWE124_Buffer_Underwrite__malloc_char_memcpy() { free(dataBuffer); } #endif + +//===----------------------------------------------------------------------=== +// strxfrm() +// It is not a built-in. +//===----------------------------------------------------------------------=== + +size_t strxfrm(char *dest, const char *src, size_t n); + +void strxfrm_null_dest(const char *src) { + strxfrm(NULL, src, 0); // no warning + strxfrm(NULL, src, 10); // expected-warning {{Null pointer passed as 1st argument}} +} + +void strxfrm_null_source(char *dest) { + strxfrm(dest, NULL, 0); // expected-warning {{Null pointer passed as 2nd argument}} +} + +#ifndef SUPPRESS_OUT_OF_BOUND +void strxfrm_overflow(const char *src) { + char dest[10]; + strxfrm(dest, src, 55); // expected-warning {{Locale transformation function overflows the destination buffer}} +} +#endif + +void strxfrm_source_smaller() { + char dest[10]; + char source[5]; + strxfrm(dest, source, 10); +} + +void strxfrm_overlap(char *dest) { + strxfrm(dest, dest, 10); // expected-warning {{Arguments must not be overlapping buffers}} +} + +void strxfrm_regular(const char *src) { + size_t n = strxfrm(NULL, src, 0); + char *dest = (char*)malloc(n + 1); + strxfrm(dest, src, n); + free(dest); +} + +void clang_analyzer_warnIfReached(); + +int strxfrm_dest_undef(const char *src, int oracle) { + char dest[5] = {0}; + clang_analyzer_eval(dest[0] == 0); // expected-warning {{TRUE}} + + size_t n = strxfrm(dest, src, sizeof(dest)); + + if (oracle >= sizeof(dest) || oracle < 0) { + return 0; + } + + int c = 0; + if (n >= sizeof(dest)) { + // Since accessing uninitialized sinks the execution, use this trick to check all positions + switch (oracle) { + case 0: + c = dest[0]; // expected-warning {{Assigned value is uninitialized}} + break; + case 1: + c = dest[1]; // expected-warning {{Assigned value is uninitialized}} + break; + case 2: + c = dest[2]; // expected-warning {{Assigned value is uninitialized}} + break; + case 3: + c = dest[3]; // expected-warning {{Assigned value is uninitialized}} + break; + case 4: + c = dest[4]; // expected-warning {{Assigned value is uninitialized}} + break; + default: + clang_analyzer_warnIfReached(); + } + } else { + clang_analyzer_eval(n >= 0); // expected-warning {{TRUE}} + clang_analyzer_eval(dest[0] == 0); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(dest[1] == 0); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(dest[2] == 0); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(dest[3] == 0); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(dest[4] == 0); // expected-warning {{UNKNOWN}} + } + return c; +} + +int strxfrm_unknown_dest_undef(const char *src, int oracle) { + size_t n = strlen(src); + + char *dest = (char*)malloc(n * 2); + + size_t n2 = strxfrm(dest, src, n); + + int c = 0; + + if (n2 < n) { + c += dest[50]; + } else { + c += dest[50]; // expected-warning {{Assigned value is uninitialized}} + } + + free(dest); + return c; +} |
