string.c revision a0decc9a2481f938e1675b4f7bbd58761a882a36
1// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s 2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s 3// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s 4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core.experimental.CString -analyzer-checker=core.experimental.UnreachableCode -analyzer-check-objc-mem -analyzer-store=region -verify %s 5 6//===----------------------------------------------------------------------=== 7// Declarations 8//===----------------------------------------------------------------------=== 9 10// Some functions are so similar to each other that they follow the same code 11// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is 12// defined, make sure to use the variants instead to make sure they are still 13// checked by the analyzer. 14 15// Some functions are implemented as builtins. These should be #defined as 16// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. 17 18// Functions that have variants and are also availabe as builtins should be 19// declared carefully! See memcpy() for an example. 20 21#ifdef USE_BUILTINS 22# define BUILTIN(f) __builtin_ ## f 23#else /* USE_BUILTINS */ 24# define BUILTIN(f) f 25#endif /* USE_BUILTINS */ 26 27#define NULL 0 28typedef typeof(sizeof(int)) size_t; 29 30//===----------------------------------------------------------------------=== 31// strlen() 32//===----------------------------------------------------------------------=== 33 34#define strlen BUILTIN(strlen) 35size_t strlen(const char *s); 36 37void strlen_constant0() { 38 if (strlen("123") != 3) 39 (void)*(char*)0; // no-warning 40} 41 42void strlen_constant1() { 43 const char *a = "123"; 44 if (strlen(a) != 3) 45 (void)*(char*)0; // no-warning 46} 47 48void strlen_constant2(char x) { 49 char a[] = "123"; 50 if (strlen(a) != 3) 51 (void)*(char*)0; // no-warning 52 a[0] = x; 53 if (strlen(a) != 3) 54 (void)*(char*)0; // expected-warning{{null}} 55} 56 57size_t strlen_null() { 58 return strlen(0); // expected-warning{{Null pointer argument in call to byte string function}} 59} 60 61size_t strlen_fn() { 62 return strlen((char*)&strlen_fn); // expected-warning{{Argument to byte string function is the address of the function 'strlen_fn', which is not a null-terminated string}} 63} 64 65size_t strlen_nonloc() { 66label: 67 return strlen((char*)&&label); // expected-warning{{Argument to byte string function is the address of the label 'label', which is not a null-terminated string}} 68} 69 70void strlen_subregion() { 71 struct two_strings { char a[2], b[2] }; 72 extern void use_two_strings(struct two_strings *); 73 74 struct two_strings z; 75 use_two_strings(&z); 76 77 size_t a = strlen(z.a); 78 z.b[0] = 5; 79 size_t b = strlen(z.a); 80 if (a == 0 && b != 0) 81 (void)*(char*)0; // expected-warning{{never executed}} 82 83 use_two_strings(&z); 84 85 size_t c = strlen(z.a); 86 if (a == 0 && c != 0) 87 (void)*(char*)0; // expected-warning{{null}} 88} 89 90extern void use_string(char *); 91void strlen_argument(char *x) { 92 size_t a = strlen(x); 93 size_t b = strlen(x); 94 if (a == 0 && b != 0) 95 (void)*(char*)0; // expected-warning{{never executed}} 96 97 use_string(x); 98 99 size_t c = strlen(x); 100 if (a == 0 && c != 0) 101 (void)*(char*)0; // expected-warning{{null}} 102} 103 104extern char global_str[]; 105void strlen_global() { 106 size_t a = strlen(global_str); 107 size_t b = strlen(global_str); 108 if (a == 0 && b != 0) 109 (void)*(char*)0; // expected-warning{{never executed}} 110 111 // Call a function with unknown effects, which should invalidate globals. 112 use_string(0); 113 114 size_t c = strlen(global_str); 115 if (a == 0 && c != 0) 116 (void)*(char*)0; // expected-warning{{null}} 117} 118 119void strlen_indirect(char *x) { 120 size_t a = strlen(x); 121 char *p = x; 122 char **p2 = &p; 123 size_t b = strlen(x); 124 if (a == 0 && b != 0) 125 (void)*(char*)0; // expected-warning{{never executed}} 126 127 extern void use_string_ptr(char*const*); 128 use_string_ptr(p2); 129 130 size_t c = strlen(x); 131 if (a == 0 && c != 0) 132 (void)*(char*)0; // expected-warning{{null}} 133} 134 135void strlen_liveness(const char *x) { 136 if (strlen(x) < 5) 137 return; 138 if (strlen(x) < 5) 139 (void)*(char*)0; // no-warning 140} 141 142//===----------------------------------------------------------------------=== 143// strcpy() 144//===----------------------------------------------------------------------=== 145 146#ifdef VARIANT 147 148#define __strcpy_chk BUILTIN(__strcpy_chk) 149char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 150 151#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1) 152 153#else /* VARIANT */ 154 155#define strcpy BUILTIN(strcpy) 156char *strcpy(char *restrict s1, const char *restrict s2); 157 158#endif /* VARIANT */ 159 160 161void strcpy_null_dst(char *x) { 162 strcpy(NULL, x); // expected-warning{{Null pointer argument in call to byte string function}} 163} 164 165void strcpy_null_src(char *x) { 166 strcpy(x, NULL); // expected-warning{{Null pointer argument in call to byte string function}} 167} 168 169void strcpy_fn(char *x) { 170 strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to byte string function is the address of the function 'strcpy_fn', which is not a null-terminated string}} 171} 172 173void strcpy_effects(char *x, char *y) { 174 char a = x[0]; 175 176 if (strcpy(x, y) != x) 177 (void)*(char*)0; // no-warning 178 179 if (strlen(x) != strlen(y)) 180 (void)*(char*)0; // no-warning 181 182 if (a != x[0]) 183 (void)*(char*)0; // expected-warning{{null}} 184} 185 186void strcpy_overflow(char *y) { 187 char x[4]; 188 if (strlen(y) == 4) 189 strcpy(x, y); // expected-warning{{Byte string function overflows destination buffer}} 190} 191 192void strcpy_no_overflow(char *y) { 193 char x[4]; 194 if (strlen(y) == 3) 195 strcpy(x, y); // no-warning 196} 197 198//===----------------------------------------------------------------------=== 199// stpcpy() 200//===----------------------------------------------------------------------=== 201 202#ifdef VARIANT 203 204#define __stpcpy_chk BUILTIN(__stpcpy_chk) 205char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 206 207#define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1) 208 209#else /* VARIANT */ 210 211#define stpcpy BUILTIN(stpcpy) 212char *stpcpy(char *restrict s1, const char *restrict s2); 213 214#endif /* VARIANT */ 215 216 217void stpcpy_effect(char *x, char *y) { 218 char a = x[0]; 219 220 if (stpcpy(x, y) != &x[strlen(y)]) 221 (void)*(char*)0; // no-warning 222 223 if (strlen(x) != strlen(y)) 224 (void)*(char*)0; // no-warning 225 226 if (a != x[0]) 227 (void)*(char*)0; // expected-warning{{null}} 228} 229 230void stpcpy_overflow(char *y) { 231 char x[4]; 232 if (strlen(y) == 4) 233 stpcpy(x, y); // expected-warning{{Byte string function overflows destination buffer}} 234} 235 236void stpcpy_no_overflow(char *y) { 237 char x[4]; 238 if (strlen(y) == 3) 239 stpcpy(x, y); // no-warning 240} 241