string-fail.c revision 793bff3fb7ca2a31e81aa7f4f3f21f921459010b
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.experimental.CString,deadcode.experimental.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s 2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,cplusplus.experimental.CString,deadcode.experimental.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s 3// XFAIL: * 4 5// This file is for tests that may eventually go into string.c, or may be 6// deleted outright. At one point these tests passed, but only because we 7// weren't correctly modelling the behavior of the relevant string functions. 8// The tests aren't incorrect, but require the analyzer to be smarter about 9// conjured values than it currently is. 10 11//===----------------------------------------------------------------------=== 12// Declarations 13//===----------------------------------------------------------------------=== 14 15// Some functions are so similar to each other that they follow the same code 16// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is 17// defined, make sure to use the variants instead to make sure they are still 18// checked by the analyzer. 19 20// Some functions are implemented as builtins. These should be #defined as 21// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. 22 23// Functions that have variants and are also available as builtins should be 24// declared carefully! See memcpy() for an example. 25 26#ifdef USE_BUILTINS 27# define BUILTIN(f) __builtin_ ## f 28#else /* USE_BUILTINS */ 29# define BUILTIN(f) f 30#endif /* USE_BUILTINS */ 31 32#define NULL 0 33typedef typeof(sizeof(int)) size_t; 34 35 36//===----------------------------------------------------------------------=== 37// strnlen() 38//===----------------------------------------------------------------------=== 39 40#define strnlen BUILTIN(strnlen) 41size_t strnlen(const char *s, size_t maxlen); 42 43void strnlen_liveness(const char *x) { 44 if (strnlen(x, 10) < 5) 45 return; 46 if (strnlen(x, 10) < 5) 47 (void)*(char*)0; // no-warning 48} 49 50void strnlen_subregion() { 51 struct two_stringsn { char a[2], b[2]; }; 52 extern void use_two_stringsn(struct two_stringsn *); 53 54 struct two_stringsn z; 55 use_two_stringsn(&z); 56 57 size_t a = strnlen(z.a, 10); 58 z.b[0] = 5; 59 size_t b = strnlen(z.a, 10); 60 if (a == 0 && b != 0) 61 (void)*(char*)0; // expected-warning{{never executed}} 62 63 use_two_stringsn(&z); 64 65 size_t c = strnlen(z.a, 10); 66 if (a == 0 && c != 0) 67 (void)*(char*)0; // expected-warning{{null}} 68} 69 70extern void use_stringn(char *); 71void strnlen_argument(char *x) { 72 size_t a = strnlen(x, 10); 73 size_t b = strnlen(x, 10); 74 if (a == 0 && b != 0) 75 (void)*(char*)0; // expected-warning{{never executed}} 76 77 use_stringn(x); 78 79 size_t c = strnlen(x, 10); 80 if (a == 0 && c != 0) 81 (void)*(char*)0; // expected-warning{{null}} 82} 83 84extern char global_strn[]; 85void strnlen_global() { 86 size_t a = strnlen(global_strn, 10); 87 size_t b = strnlen(global_strn, 10); 88 if (a == 0 && b != 0) 89 (void)*(char*)0; // expected-warning{{never executed}} 90 91 // Call a function with unknown effects, which should invalidate globals. 92 use_stringn(0); 93 94 size_t c = strnlen(global_strn, 10); 95 if (a == 0 && c != 0) 96 (void)*(char*)0; // expected-warning{{null}} 97} 98 99void strnlen_indirect(char *x) { 100 size_t a = strnlen(x, 10); 101 char *p = x; 102 char **p2 = &p; 103 size_t b = strnlen(x, 10); 104 if (a == 0 && b != 0) 105 (void)*(char*)0; // expected-warning{{never executed}} 106 107 extern void use_stringn_ptr(char*const*); 108 use_stringn_ptr(p2); 109 110 size_t c = strnlen(x, 10); 111 if (a == 0 && c != 0) 112 (void)*(char*)0; // expected-warning{{null}} 113} 114