1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s 2 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -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 33 typedef typeof(sizeof(int)) size_t; 34 35 void clang_analyzer_eval(int); 36 37 //===----------------------------------------------------------------------=== 38 // strnlen() 39 //===----------------------------------------------------------------------=== 40 41 #define strnlen BUILTIN(strnlen) 42 size_t strnlen(const char *s, size_t maxlen); 43 44 void strnlen_liveness(const char *x) { 45 if (strnlen(x, 10) < 5) 46 return; 47 clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}} 48 } 49 50 void 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) 61 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 62 63 use_two_stringsn(&z); 64 65 size_t c = strnlen(z.a, 10); 66 if (a == 0) 67 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 68 } 69 70 extern void use_stringn(char *); 71 void strnlen_argument(char *x) { 72 size_t a = strnlen(x, 10); 73 size_t b = strnlen(x, 10); 74 if (a == 0) 75 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 76 77 use_stringn(x); 78 79 size_t c = strnlen(x, 10); 80 if (a == 0) 81 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 82 } 83 84 extern char global_strn[]; 85 void strnlen_global() { 86 size_t a = strnlen(global_strn, 10); 87 size_t b = strnlen(global_strn, 10); 88 if (a == 0) 89 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 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) 96 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 97 } 98 99 void 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) 105 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 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) 112 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 113 } 114