| 1 | // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
| 2 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
| 3 | // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -w %s |
| 4 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s |
| 5 | |
| 6 | extern void clang_analyzer_eval(_Bool); |
| 7 | |
| 8 | // Test if the 'storage' region gets properly initialized after it is cast to |
| 9 | // 'struct sockaddr *'. |
| 10 | |
| 11 | typedef unsigned char __uint8_t; |
| 12 | typedef unsigned int __uint32_t; |
| 13 | typedef __uint32_t __darwin_socklen_t; |
| 14 | typedef __uint8_t sa_family_t; |
| 15 | typedef __darwin_socklen_t socklen_t; |
| 16 | struct sockaddr { sa_family_t sa_family; }; |
| 17 | struct sockaddr_storage {}; |
| 18 | |
| 19 | void getsockname(); |
| 20 | |
| 21 | #ifndef EAGERLY_ASSUME |
| 22 | |
| 23 | void f(int sock) { |
| 24 | struct sockaddr_storage storage; |
| 25 | struct sockaddr* sockaddr = (struct sockaddr*)&storage; // expected-warning{{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}} |
| 26 | socklen_t addrlen = sizeof(storage); |
| 27 | getsockname(sock, sockaddr, &addrlen); |
| 28 | switch (sockaddr->sa_family) { // no-warning |
| 29 | default: |
| 30 | ; |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | struct s { |
| 35 | struct s *value; |
| 36 | }; |
| 37 | |
| 38 | void f1(struct s **pval) { |
| 39 | int *tbool = ((void*)0); |
| 40 | struct s *t = *pval; |
| 41 | pval = &(t->value); |
| 42 | tbool = (int *)pval; // use the cast-to type 'int *' to create element region. |
| 43 | char c = (unsigned char) *tbool; // Should use cast-to type to create symbol. |
| 44 | if (*tbool == -1) // here load the element region with the correct type 'int' |
| 45 | (void)3; |
| 46 | } |
| 47 | |
| 48 | void f2(const char *str) { |
| 49 | unsigned char ch, cl, *p; |
| 50 | |
| 51 | p = (unsigned char *)str; |
| 52 | ch = *p++; // use cast-to type 'unsigned char' to create element region. |
| 53 | cl = *p++; |
| 54 | if(!cl) |
| 55 | cl = 'a'; |
| 56 | } |
| 57 | |
| 58 | // Test cast VariableSizeArray to pointer does not crash. |
| 59 | void *memcpy(void *, void const *, unsigned long); |
| 60 | typedef unsigned char Byte; |
| 61 | void doit(char *data, int len) { |
| 62 | if (len) { |
| 63 | Byte buf[len]; |
| 64 | memcpy(buf, data, len); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | // PR 6013 and 6035 - Test that a cast of a pointer to long and then to int does not crash SValuator. |
| 69 | void pr6013_6035_test(void *p) { |
| 70 | unsigned int foo; |
| 71 | foo = ((long)(p)); |
| 72 | (void) foo; |
| 73 | } |
| 74 | |
| 75 | // PR12511 and radar://11215362 - Test that we support SymCastExpr, which represents symbolic int to float cast. |
| 76 | char ttt(int intSeconds) { |
| 77 | double seconds = intSeconds; |
| 78 | if (seconds) |
| 79 | return 0; |
| 80 | return 0; |
| 81 | } |
| 82 | |
| 83 | int foo (int* p) { |
| 84 | int y = 0; |
| 85 | if (p == 0) { |
| 86 | if ((*((void**)&p)) == (void*)0) // Test that the cast to void preserves the symbolic region. |
| 87 | return 0; |
| 88 | else |
| 89 | return 5/y; // This code should be unreachable: no-warning. |
| 90 | } |
| 91 | return 0; |
| 92 | } |
| 93 | |
| 94 | void castsToBool() { |
| 95 | clang_analyzer_eval(0); // expected-warning{{FALSE}} |
| 96 | clang_analyzer_eval(0U); // expected-warning{{FALSE}} |
| 97 | clang_analyzer_eval((void *)0); // expected-warning{{FALSE}} |
| 98 | |
| 99 | clang_analyzer_eval(1); // expected-warning{{TRUE}} |
| 100 | clang_analyzer_eval(1U); // expected-warning{{TRUE}} |
| 101 | clang_analyzer_eval(-1); // expected-warning{{TRUE}} |
| 102 | clang_analyzer_eval(0x100); // expected-warning{{TRUE}} |
| 103 | clang_analyzer_eval(0x100U); // expected-warning{{TRUE}} |
| 104 | clang_analyzer_eval((void *)0x100); // expected-warning{{TRUE}} |
| 105 | |
| 106 | extern int symbolicInt; |
| 107 | clang_analyzer_eval(symbolicInt); // expected-warning{{UNKNOWN}} |
| 108 | if (symbolicInt) |
| 109 | clang_analyzer_eval(symbolicInt); // expected-warning{{TRUE}} |
| 110 | |
| 111 | extern void *symbolicPointer; |
| 112 | clang_analyzer_eval(symbolicPointer); // expected-warning{{UNKNOWN}} |
| 113 | if (symbolicPointer) |
| 114 | clang_analyzer_eval(symbolicPointer); // expected-warning{{TRUE}} |
| 115 | |
| 116 | int localInt; |
| 117 | int* ptr = &localInt; |
| 118 | clang_analyzer_eval(ptr); // expected-warning{{TRUE}} |
| 119 | clang_analyzer_eval(&castsToBool); // expected-warning{{TRUE}} |
| 120 | clang_analyzer_eval("abc"); // expected-warning{{TRUE}} |
| 121 | |
| 122 | extern float globalFloat; |
| 123 | clang_analyzer_eval(globalFloat); // expected-warning{{UNKNOWN}} |
| 124 | } |
| 125 | |
| 126 | void locAsIntegerCasts(void *p) { |
| 127 | int x = (int) p; |
| 128 | clang_analyzer_eval(++x < 10); // no-crash // expected-warning{{UNKNOWN}} |
| 129 | } |
| 130 | |
| 131 | void multiDimensionalArrayPointerCasts() { |
| 132 | static int x[10][10]; |
| 133 | int *y1 = &(x[3][5]); |
| 134 | char *z = ((char *) y1) + 2; |
| 135 | int *y2 = (int *)(z - 2); |
| 136 | int *y3 = ((int *)x) + 35; // This is offset for [3][5]. |
| 137 | |
| 138 | clang_analyzer_eval(y1 == y2); // expected-warning{{TRUE}} |
| 139 | |
| 140 | // FIXME: should be FALSE (i.e. equal pointers). |
| 141 | clang_analyzer_eval(y1 - y2); // expected-warning{{UNKNOWN}} |
| 142 | // FIXME: should be TRUE (i.e. same symbol). |
| 143 | clang_analyzer_eval(*y1 == *y2); // expected-warning{{UNKNOWN}} |
| 144 | |
| 145 | clang_analyzer_eval(*((char *)y1) == *((char *) y2)); // expected-warning{{TRUE}} |
| 146 | |
| 147 | clang_analyzer_eval(y1 == y3); // expected-warning{{TRUE}} |
| 148 | |
| 149 | // FIXME: should be FALSE (i.e. equal pointers). |
| 150 | clang_analyzer_eval(y1 - y3); // expected-warning{{UNKNOWN}} |
| 151 | // FIXME: should be TRUE (i.e. same symbol). |
| 152 | clang_analyzer_eval(*y1 == *y3); // expected-warning{{UNKNOWN}} |
| 153 | |
| 154 | clang_analyzer_eval(*((char *)y1) == *((char *) y3)); // expected-warning{{TRUE}} |
| 155 | } |
| 156 | |
| 157 | void *getVoidPtr(); |
| 158 | |
| 159 | void testCastVoidPtrToIntPtrThroughIntTypedAssignment() { |
| 160 | int *x; |
| 161 | (*((int *)(&x))) = (int)getVoidPtr(); |
| 162 | *x = 1; // no-crash |
| 163 | } |
| 164 | |
| 165 | void testCastUIntPtrToIntPtrThroughIntTypedAssignment() { |
| 166 | unsigned u; |
| 167 | int *x; |
| 168 | (*((int *)(&x))) = (int)&u; |
| 169 | *x = 1; |
| 170 | clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} |
| 171 | } |
| 172 | |
| 173 | void testCastVoidPtrToIntPtrThroughUIntTypedAssignment() { |
| 174 | int *x; |
| 175 | (*((int *)(&x))) = (int)(unsigned *)getVoidPtr(); |
| 176 | *x = 1; // no-crash |
| 177 | } |
| 178 | |
| 179 | void testLocNonLocSymbolAssume(int a, int *b) { |
| 180 | if ((int)b < a) {} // no-crash |
| 181 | } |
| 182 | |
| 183 | void testLocNonLocSymbolRemainder(int a, int *b) { |
| 184 | int c = ((int)b) % a; |
| 185 | if (a == 1) { |
| 186 | c += 1; |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | void testSwitchWithSizeofs() { |
| 191 | switch (sizeof(char) == 1) { // expected-warning{{switch condition has boolean value}} |
| 192 | case sizeof(char):; // no-crash |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | #endif |
| 197 | |
| 198 | #ifdef EAGERLY_ASSUME |
| 199 | |
| 200 | int globalA; |
| 201 | extern int globalFunc(); |
| 202 | void no_crash_on_symsym_cast_to_long() { |
| 203 | char c = globalFunc() - 5; |
| 204 | c == 0; |
| 205 | globalA -= c; |
| 206 | globalA == 3; |
| 207 | (long)globalA << 48; |
| 208 | #ifdef BIT32 |
| 209 | // expected-warning@-2{{The result of the left shift is undefined due to shifting by '48', which is greater or equal to the width of type 'long'}} |
| 210 | #else |
| 211 | // expected-no-diagnostics |
| 212 | #endif |
| 213 | } |
| 214 | |
| 215 | #endif |
| 216 | |
| 217 | char no_crash_SymbolCast_of_float_type_aux(int *p) { |
| 218 | *p += 1; |
| 219 | return *p; |
| 220 | } |
| 221 | |
| 222 | void no_crash_SymbolCast_of_float_type() { |
| 223 | extern float x; |
| 224 | char (*f)() = no_crash_SymbolCast_of_float_type_aux; |
| 225 | f(&x); |
| 226 | } |
| 227 | |
| 228 | double no_crash_reinterpret_double_as_int(double a) { |
| 229 | *(int *)&a = 1; |
| 230 | return a * a; |
| 231 | } |
| 232 | |
| 233 | double no_crash_reinterpret_double_as_ptr(double a) { |
| 234 | *(void **)&a = 0; |
| 235 | return a * a; |
| 236 | } |
| 237 | |
| 238 | double no_crash_reinterpret_double_as_sym_int(double a, int b) { |
| 239 | *(int *)&a = b; |
| 240 | return a * a; |
| 241 | } |
| 242 | |
| 243 | double no_crash_reinterpret_double_as_sym_ptr(double a, void * b) { |
| 244 | *(void **)&a = b; |
| 245 | return a * a; |
| 246 | } |
| 247 | |
| 248 | |