1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s 2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s 3// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s 4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -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 available 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 27typedef typeof(sizeof(int)) size_t; 28 29void clang_analyzer_eval(int); 30 31//===----------------------------------------------------------------------=== 32// memcpy() 33//===----------------------------------------------------------------------=== 34 35#ifdef VARIANT 36 37#define __memcpy_chk BUILTIN(__memcpy_chk) 38void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n, 39 size_t destlen); 40 41#define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1) 42 43#else /* VARIANT */ 44 45#define memcpy BUILTIN(memcpy) 46void *memcpy(void *restrict s1, const void *restrict s2, size_t n); 47 48#endif /* VARIANT */ 49 50 51void memcpy0 () { 52 char src[] = {1, 2, 3, 4}; 53 char dst[4] = {0}; 54 55 memcpy(dst, src, 4); // no-warning 56 57 clang_analyzer_eval(memcpy(dst, src, 4) == dst); // expected-warning{{TRUE}} 58 59 // If we actually model the copy, we can make this known. 60 // The important thing for now is that the old value has been invalidated. 61 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} 62} 63 64void memcpy1 () { 65 char src[] = {1, 2, 3, 4}; 66 char dst[10]; 67 68 memcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}} 69} 70 71void memcpy2 () { 72 char src[] = {1, 2, 3, 4}; 73 char dst[1]; 74 75 memcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}} 76} 77 78void memcpy3 () { 79 char src[] = {1, 2, 3, 4}; 80 char dst[3]; 81 82 memcpy(dst+1, src+2, 2); // no-warning 83} 84 85void memcpy4 () { 86 char src[] = {1, 2, 3, 4}; 87 char dst[10]; 88 89 memcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}} 90} 91 92void memcpy5() { 93 char src[] = {1, 2, 3, 4}; 94 char dst[3]; 95 96 memcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}} 97} 98 99void memcpy6() { 100 int a[4] = {0}; 101 memcpy(a, a, 8); // expected-warning{{overlapping}} 102} 103 104void memcpy7() { 105 int a[4] = {0}; 106 memcpy(a+2, a+1, 8); // expected-warning{{overlapping}} 107} 108 109void memcpy8() { 110 int a[4] = {0}; 111 memcpy(a+1, a+2, 8); // expected-warning{{overlapping}} 112} 113 114void memcpy9() { 115 int a[4] = {0}; 116 memcpy(a+2, a+1, 4); // no-warning 117 memcpy(a+1, a+2, 4); // no-warning 118} 119 120void memcpy10() { 121 char a[4] = {0}; 122 memcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}} 123} 124 125void memcpy11() { 126 char a[4] = {0}; 127 memcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}} 128} 129 130void memcpy12() { 131 char a[4] = {0}; 132 memcpy(0, a, 0); // no-warning 133} 134 135void memcpy13() { 136 char a[4] = {0}; 137 memcpy(a, 0, 0); // no-warning 138} 139 140void memcpy_unknown_size (size_t n) { 141 char a[4], b[4] = {1}; 142 clang_analyzer_eval(memcpy(a, b, n) == a); // expected-warning{{TRUE}} 143} 144 145void memcpy_unknown_size_warn (size_t n) { 146 char a[4]; 147 void *result = memcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}} 148 clang_analyzer_eval(result == a); // no-warning (above is fatal) 149} 150 151//===----------------------------------------------------------------------=== 152// mempcpy() 153//===----------------------------------------------------------------------=== 154 155#ifdef VARIANT 156 157#define __mempcpy_chk BUILTIN(__mempcpy_chk) 158void *__mempcpy_chk(void *restrict s1, const void *restrict s2, size_t n, 159 size_t destlen); 160 161#define mempcpy(a,b,c) __mempcpy_chk(a,b,c,(size_t)-1) 162 163#else /* VARIANT */ 164 165#define mempcpy BUILTIN(mempcpy) 166void *mempcpy(void *restrict s1, const void *restrict s2, size_t n); 167 168#endif /* VARIANT */ 169 170 171void mempcpy0 () { 172 char src[] = {1, 2, 3, 4}; 173 char dst[5] = {0}; 174 175 mempcpy(dst, src, 4); // no-warning 176 177 clang_analyzer_eval(mempcpy(dst, src, 4) == &dst[4]); // expected-warning{{TRUE}} 178 179 // If we actually model the copy, we can make this known. 180 // The important thing for now is that the old value has been invalidated. 181 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} 182} 183 184void mempcpy1 () { 185 char src[] = {1, 2, 3, 4}; 186 char dst[10]; 187 188 mempcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}} 189} 190 191void mempcpy2 () { 192 char src[] = {1, 2, 3, 4}; 193 char dst[1]; 194 195 mempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}} 196} 197 198void mempcpy3 () { 199 char src[] = {1, 2, 3, 4}; 200 char dst[3]; 201 202 mempcpy(dst+1, src+2, 2); // no-warning 203} 204 205void mempcpy4 () { 206 char src[] = {1, 2, 3, 4}; 207 char dst[10]; 208 209 mempcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}} 210} 211 212void mempcpy5() { 213 char src[] = {1, 2, 3, 4}; 214 char dst[3]; 215 216 mempcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}} 217} 218 219void mempcpy6() { 220 int a[4] = {0}; 221 mempcpy(a, a, 8); // expected-warning{{overlapping}} 222} 223 224void mempcpy7() { 225 int a[4] = {0}; 226 mempcpy(a+2, a+1, 8); // expected-warning{{overlapping}} 227} 228 229void mempcpy8() { 230 int a[4] = {0}; 231 mempcpy(a+1, a+2, 8); // expected-warning{{overlapping}} 232} 233 234void mempcpy9() { 235 int a[4] = {0}; 236 mempcpy(a+2, a+1, 4); // no-warning 237 mempcpy(a+1, a+2, 4); // no-warning 238} 239 240void mempcpy10() { 241 char a[4] = {0}; 242 mempcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}} 243} 244 245void mempcpy11() { 246 char a[4] = {0}; 247 mempcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}} 248} 249 250void mempcpy12() { 251 char a[4] = {0}; 252 mempcpy(0, a, 0); // no-warning 253} 254 255void mempcpy13() { 256 char a[4] = {0}; 257 mempcpy(a, 0, 0); // no-warning 258} 259 260void mempcpy14() { 261 int src[] = {1, 2, 3, 4}; 262 int dst[5] = {0}; 263 int *p; 264 265 p = mempcpy(dst, src, 4 * sizeof(int)); 266 267 clang_analyzer_eval(p == &dst[4]); // expected-warning{{TRUE}} 268} 269 270struct st { 271 int i; 272 int j; 273}; 274 275void mempcpy15() { 276 struct st s1 = {0}; 277 struct st s2; 278 struct st *p1; 279 struct st *p2; 280 281 p1 = (&s2) + 1; 282 p2 = mempcpy(&s2, &s1, sizeof(struct st)); 283 284 clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}} 285} 286 287void mempcpy16() { 288 struct st s1[10] = {{0}}; 289 struct st s2[10]; 290 struct st *p1; 291 struct st *p2; 292 293 p1 = (&s2[0]) + 5; 294 p2 = mempcpy(&s2[0], &s1[0], 5 * sizeof(struct st)); 295 296 clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}} 297} 298 299void mempcpy_unknown_size_warn (size_t n) { 300 char a[4]; 301 void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}} 302 clang_analyzer_eval(result == a); // no-warning (above is fatal) 303} 304 305void mempcpy_unknownable_size (char *src, float n) { 306 char a[4]; 307 // This used to crash because we don't model floats. 308 mempcpy(a, src, (size_t)n); 309} 310 311//===----------------------------------------------------------------------=== 312// memmove() 313//===----------------------------------------------------------------------=== 314 315#ifdef VARIANT 316 317#define __memmove_chk BUILTIN(__memmove_chk) 318void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen); 319 320#define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1) 321 322#else /* VARIANT */ 323 324#define memmove BUILTIN(memmove) 325void *memmove(void *s1, const void *s2, size_t n); 326 327#endif /* VARIANT */ 328 329 330void memmove0 () { 331 char src[] = {1, 2, 3, 4}; 332 char dst[4] = {0}; 333 334 memmove(dst, src, 4); // no-warning 335 336 clang_analyzer_eval(memmove(dst, src, 4) == dst); // expected-warning{{TRUE}} 337 338 // If we actually model the copy, we can make this known. 339 // The important thing for now is that the old value has been invalidated. 340 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} 341} 342 343void memmove1 () { 344 char src[] = {1, 2, 3, 4}; 345 char dst[10]; 346 347 memmove(dst, src, 5); // expected-warning{{out-of-bound}} 348} 349 350void memmove2 () { 351 char src[] = {1, 2, 3, 4}; 352 char dst[1]; 353 354 memmove(dst, src, 4); // expected-warning{{overflow}} 355} 356 357//===----------------------------------------------------------------------=== 358// memcmp() 359//===----------------------------------------------------------------------=== 360 361#ifdef VARIANT 362 363#define bcmp BUILTIN(bcmp) 364// __builtin_bcmp is not defined with const in Builtins.def. 365int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n); 366#define memcmp bcmp 367// 368#else /* VARIANT */ 369 370#define memcmp BUILTIN(memcmp) 371int memcmp(const void *s1, const void *s2, size_t n); 372 373#endif /* VARIANT */ 374 375 376void memcmp0 () { 377 char a[] = {1, 2, 3, 4}; 378 char b[4] = { 0 }; 379 380 memcmp(a, b, 4); // no-warning 381} 382 383void memcmp1 () { 384 char a[] = {1, 2, 3, 4}; 385 char b[10] = { 0 }; 386 387 memcmp(a, b, 5); // expected-warning{{out-of-bound}} 388} 389 390void memcmp2 () { 391 char a[] = {1, 2, 3, 4}; 392 char b[1] = { 0 }; 393 394 memcmp(a, b, 4); // expected-warning{{out-of-bound}} 395} 396 397void memcmp3 () { 398 char a[] = {1, 2, 3, 4}; 399 400 clang_analyzer_eval(memcmp(a, a, 4) == 0); // expected-warning{{TRUE}} 401} 402 403void memcmp4 (char *input) { 404 char a[] = {1, 2, 3, 4}; 405 406 clang_analyzer_eval(memcmp(a, input, 4) == 0); // expected-warning{{UNKNOWN}} 407} 408 409void memcmp5 (char *input) { 410 char a[] = {1, 2, 3, 4}; 411 412 clang_analyzer_eval(memcmp(a, 0, 0) == 0); // expected-warning{{TRUE}} 413 clang_analyzer_eval(memcmp(0, a, 0) == 0); // expected-warning{{TRUE}} 414 clang_analyzer_eval(memcmp(a, input, 0) == 0); // expected-warning{{TRUE}} 415} 416 417void memcmp6 (char *a, char *b, size_t n) { 418 int result = memcmp(a, b, n); 419 if (result != 0) 420 clang_analyzer_eval(n != 0); // expected-warning{{TRUE}} 421 // else 422 // analyzer_assert_unknown(n == 0); 423 424 // We can't do the above comparison because n has already been constrained. 425 // On one path n == 0, on the other n != 0. 426} 427 428int memcmp7 (char *a, size_t x, size_t y, size_t n) { 429 // We used to crash when either of the arguments was unknown. 430 return memcmp(a, &a[x*y], n) + 431 memcmp(&a[x*y], a, n); 432} 433 434//===----------------------------------------------------------------------=== 435// bcopy() 436//===----------------------------------------------------------------------=== 437 438#define bcopy BUILTIN(bcopy) 439// __builtin_bcopy is not defined with const in Builtins.def. 440void bcopy(/*const*/ void *s1, void *s2, size_t n); 441 442 443void bcopy0 () { 444 char src[] = {1, 2, 3, 4}; 445 char dst[4] = {0}; 446 447 bcopy(src, dst, 4); // no-warning 448 449 // If we actually model the copy, we can make this known. 450 // The important thing for now is that the old value has been invalidated. 451 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} 452} 453 454void bcopy1 () { 455 char src[] = {1, 2, 3, 4}; 456 char dst[10]; 457 458 bcopy(src, dst, 5); // expected-warning{{out-of-bound}} 459} 460 461void bcopy2 () { 462 char src[] = {1, 2, 3, 4}; 463 char dst[1]; 464 465 bcopy(src, dst, 4); // expected-warning{{overflow}} 466} 467 468void *malloc(size_t); 469void free(void *); 470char radar_11125445_memcopythenlogfirstbyte(const char *input, size_t length) { 471 char *bytes = malloc(sizeof(char) * (length + 1)); 472 memcpy(bytes, input, length); 473 char x = bytes[0]; // no warning 474 free(bytes); 475 return x; 476} 477