1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare %s 2 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare %s 3 4 void clang_analyzer_eval(int); 5 6 void f1() { 7 int a[10]; 8 int *p = a; 9 ++p; 10 } 11 12 char* foo(); 13 14 void f2() { 15 char *p = foo(); 16 ++p; 17 } 18 19 // This test case checks if we get the right rvalue type of a TypedViewRegion. 20 // The ElementRegion's type depends on the array region's rvalue type. If it was 21 // a pointer type, we would get a loc::SymbolVal for '*p'. 22 void* memchr(); 23 static int 24 domain_port (const char *domain_b, const char *domain_e, 25 const char **domain_e_ptr) 26 { 27 int port = 0; 28 29 const char *p; 30 const char *colon = memchr (domain_b, ':', domain_e - domain_b); 31 32 for (p = colon + 1; p < domain_e ; p++) 33 port = 10 * port + (*p - '0'); 34 return port; 35 } 36 37 void f3() { 38 int x, y; 39 int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result}} 40 41 int a[10]; 42 int *p = &a[2]; 43 int *q = &a[8]; 44 d = q-p; // no-warning 45 } 46 47 void f4() { 48 int *p; 49 p = (int*) 0x10000; // expected-warning{{Using a fixed address is not portable because that address will probably not be valid in all environments or platforms}} 50 } 51 52 void f5() { 53 int x, y; 54 int *p; 55 p = &x + 1; // expected-warning{{Pointer arithmetic on non-array variables relies on memory layout, which is dangerous}} 56 57 int a[10]; 58 p = a + 1; // no-warning 59 } 60 61 // Allow arithmetic on different symbolic regions. 62 void f6(int *p, int *q) { 63 int d = q - p; // no-warning 64 } 65 66 void null_operand(int *a) { 67 start: 68 // LHS is a label, RHS is NULL 69 clang_analyzer_eval(&&start != 0); // expected-warning{{TRUE}} 70 clang_analyzer_eval(&&start >= 0); // expected-warning{{TRUE}} 71 clang_analyzer_eval(&&start > 0); // expected-warning{{TRUE}} 72 clang_analyzer_eval((&&start - 0) != 0); // expected-warning{{TRUE}} 73 74 // LHS is a non-symbolic value, RHS is NULL 75 clang_analyzer_eval(&a != 0); // expected-warning{{TRUE}} 76 clang_analyzer_eval(&a >= 0); // expected-warning{{TRUE}} 77 clang_analyzer_eval(&a > 0); // expected-warning{{TRUE}} 78 clang_analyzer_eval((&a - 0) != 0); // expected-warning{{TRUE}} 79 80 // LHS is NULL, RHS is non-symbolic 81 // The same code is used for labels and non-symbolic values. 82 clang_analyzer_eval(0 != &a); // expected-warning{{TRUE}} 83 clang_analyzer_eval(0 <= &a); // expected-warning{{TRUE}} 84 clang_analyzer_eval(0 < &a); // expected-warning{{TRUE}} 85 86 // LHS is a symbolic value, RHS is NULL 87 clang_analyzer_eval(a != 0); // expected-warning{{UNKNOWN}} 88 clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}} 89 clang_analyzer_eval(a <= 0); // expected-warning{{UNKNOWN}} 90 clang_analyzer_eval((a - 0) != 0); // expected-warning{{UNKNOWN}} 91 92 // LHS is NULL, RHS is a symbolic value 93 clang_analyzer_eval(0 != a); // expected-warning{{UNKNOWN}} 94 clang_analyzer_eval(0 <= a); // expected-warning{{TRUE}} 95 clang_analyzer_eval(0 < a); // expected-warning{{UNKNOWN}} 96 } 97 98 void const_locs() { 99 char *a = (char*)0x1000; 100 char *b = (char*)0x1100; 101 start: 102 clang_analyzer_eval(a != b); // expected-warning{{TRUE}} 103 clang_analyzer_eval(a < b); // expected-warning{{TRUE}} 104 clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} 105 clang_analyzer_eval((b-a) == 0x100); // expected-warning{{TRUE}} 106 107 clang_analyzer_eval(&&start == a); // expected-warning{{UNKNOWN}} 108 clang_analyzer_eval(a == &&start); // expected-warning{{UNKNOWN}} 109 clang_analyzer_eval(&a == (char**)a); // expected-warning{{UNKNOWN}} 110 clang_analyzer_eval((char**)a == &a); // expected-warning{{UNKNOWN}} 111 } 112 113 void array_matching_types() { 114 int array[10]; 115 int *a = &array[2]; 116 int *b = &array[5]; 117 118 clang_analyzer_eval(a != b); // expected-warning{{TRUE}} 119 clang_analyzer_eval(a < b); // expected-warning{{TRUE}} 120 clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} 121 clang_analyzer_eval((b-a) != 0); // expected-warning{{TRUE}} 122 } 123 124 // This takes a different code path than array_matching_types() 125 void array_different_types() { 126 int array[10]; 127 int *a = &array[2]; 128 char *b = (char*)&array[5]; 129 130 clang_analyzer_eval(a != b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}} 131 clang_analyzer_eval(a < b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}} 132 clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}} 133 } 134 135 struct test { int x; int y; }; 136 void struct_fields() { 137 struct test a, b; 138 139 clang_analyzer_eval(&a.x != &a.y); // expected-warning{{TRUE}} 140 clang_analyzer_eval(&a.x < &a.y); // expected-warning{{TRUE}} 141 clang_analyzer_eval(&a.x <= &a.y); // expected-warning{{TRUE}} 142 143 clang_analyzer_eval(&a.x != &b.x); // expected-warning{{TRUE}} 144 clang_analyzer_eval(&a.x > &b.x); // expected-warning{{UNKNOWN}} 145 clang_analyzer_eval(&a.x >= &b.x); // expected-warning{{UNKNOWN}} 146 } 147 148 void mixed_region_types() { 149 struct test s; 150 int array[2]; 151 void *a = &array, *b = &s; 152 153 clang_analyzer_eval(&a != &b); // expected-warning{{TRUE}} 154 clang_analyzer_eval(&a > &b); // expected-warning{{UNKNOWN}} 155 clang_analyzer_eval(&a >= &b); // expected-warning{{UNKNOWN}} 156 } 157 158 void symbolic_region(int *p) { 159 int a; 160 161 clang_analyzer_eval(&a != p); // expected-warning{{TRUE}} 162 clang_analyzer_eval(&a > p); // expected-warning{{UNKNOWN}} 163 clang_analyzer_eval(&a >= p); // expected-warning{{UNKNOWN}} 164 } 165 166 void PR7527 (int *p) { 167 if (((int) p) & 1) // not crash 168 return; 169 } 170 171 void use_symbols(int *lhs, int *rhs) { 172 clang_analyzer_eval(lhs < rhs); // expected-warning{{UNKNOWN}} 173 if (lhs < rhs) 174 return; 175 clang_analyzer_eval(lhs < rhs); // expected-warning{{FALSE}} 176 177 clang_analyzer_eval(lhs - rhs); // expected-warning{{UNKNOWN}} 178 if ((lhs - rhs) != 5) 179 return; 180 clang_analyzer_eval((lhs - rhs) == 5); // expected-warning{{TRUE}} 181 } 182 183 void equal_implies_zero(int *lhs, int *rhs) { 184 clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}} 185 if (lhs == rhs) { 186 clang_analyzer_eval(lhs != rhs); // expected-warning{{FALSE}} 187 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{TRUE}} 188 return; 189 } 190 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 191 clang_analyzer_eval(lhs != rhs); // expected-warning{{TRUE}} 192 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}} 193 } 194 195 void zero_implies_equal(int *lhs, int *rhs) { 196 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}} 197 if ((rhs - lhs) == 0) { 198 clang_analyzer_eval(lhs != rhs); // expected-warning{{FALSE}} 199 clang_analyzer_eval(lhs == rhs); // expected-warning{{TRUE}} 200 return; 201 } 202 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}} 203 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 204 clang_analyzer_eval(lhs != rhs); // expected-warning{{TRUE}} 205 } 206 207 void comparisons_imply_size(int *lhs, int *rhs) { 208 clang_analyzer_eval(lhs <= rhs); // expected-warning{{UNKNOWN}} 209 210 if (lhs > rhs) { 211 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}} 212 return; 213 } 214 215 clang_analyzer_eval(lhs <= rhs); // expected-warning{{TRUE}} 216 // FIXME: In Z3ConstraintManager, ptrdiff_t is mapped to signed bitvector. However, this does not directly imply the unsigned comparison. 217 #ifdef ANALYZER_CM_Z3 218 clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{UNKNOWN}} 219 #else 220 clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{TRUE}} 221 #endif 222 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}} 223 224 if (lhs >= rhs) { 225 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{TRUE}} 226 return; 227 } 228 229 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 230 clang_analyzer_eval(lhs < rhs); // expected-warning{{TRUE}} 231 #ifdef ANALYZER_CM_Z3 232 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}} 233 #else 234 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}} 235 #endif 236 } 237 238 void size_implies_comparison(int *lhs, int *rhs) { 239 clang_analyzer_eval(lhs <= rhs); // expected-warning{{UNKNOWN}} 240 241 if ((rhs - lhs) < 0) { 242 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 243 return; 244 } 245 246 #ifdef ANALYZER_CM_Z3 247 clang_analyzer_eval(lhs <= rhs); // expected-warning{{UNKNOWN}} 248 #else 249 clang_analyzer_eval(lhs <= rhs); // expected-warning{{TRUE}} 250 #endif 251 clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{TRUE}} 252 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}} 253 254 if ((rhs - lhs) <= 0) { 255 clang_analyzer_eval(lhs == rhs); // expected-warning{{TRUE}} 256 return; 257 } 258 259 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 260 #ifdef ANALYZER_CM_Z3 261 clang_analyzer_eval(lhs < rhs); // expected-warning{{UNKNOWN}} 262 #else 263 clang_analyzer_eval(lhs < rhs); // expected-warning{{TRUE}} 264 #endif 265 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}} 266 } 267 268 //------------------------------- 269 // False positives 270 //------------------------------- 271 272 void zero_implies_reversed_equal(int *lhs, int *rhs) { 273 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}} 274 if ((rhs - lhs) == 0) { 275 #ifdef ANALYZER_CM_Z3 276 clang_analyzer_eval(rhs != lhs); // expected-warning{{FALSE}} 277 clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}} 278 #else 279 clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}} 280 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 281 #endif 282 return; 283 } 284 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}} 285 #ifdef ANALYZER_CM_Z3 286 clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}} 287 clang_analyzer_eval(rhs != lhs); // expected-warning{{TRUE}} 288 #else 289 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 290 clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}} 291 #endif 292 } 293 294 void canonical_equal(int *lhs, int *rhs) { 295 clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}} 296 if (lhs == rhs) { 297 #ifdef ANALYZER_CM_Z3 298 clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}} 299 #else 300 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 301 #endif 302 return; 303 } 304 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 305 306 #ifdef ANALYZER_CM_Z3 307 clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}} 308 #else 309 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 310 #endif 311 } 312 313 void compare_element_region_and_base(int *p) { 314 int *q = p - 1; 315 clang_analyzer_eval(p == q); // expected-warning{{FALSE}} 316 } 317 318 struct Point { 319 int x; 320 int y; 321 }; 322 void symbolicFieldRegion(struct Point *points, int i, int j) { 323 clang_analyzer_eval(&points[i].x == &points[j].x);// expected-warning{{UNKNOWN}} 324 clang_analyzer_eval(&points[i].x == &points[i].y);// expected-warning{{FALSE}} 325 clang_analyzer_eval(&points[i].x < &points[i].y);// expected-warning{{TRUE}} 326 } 327 328 void negativeIndex(char *str) { 329 *(str + 1) = 'a'; 330 clang_analyzer_eval(*(str + 1) == 'a'); // expected-warning{{TRUE}} 331 clang_analyzer_eval(*(str - 1) == 'a'); // expected-warning{{UNKNOWN}} 332 333 char *ptr1 = str - 1; 334 clang_analyzer_eval(*ptr1 == 'a'); // expected-warning{{UNKNOWN}} 335 336 char *ptr2 = str; 337 ptr2 -= 1; 338 clang_analyzer_eval(*ptr2 == 'a'); // expected-warning{{UNKNOWN}} 339 340 char *ptr3 = str; 341 --ptr3; 342 clang_analyzer_eval(*ptr3 == 'a'); // expected-warning{{UNKNOWN}} 343 } 344 345 void test_no_crash_on_pointer_to_label() { 346 char *a = &&label; 347 a[0] = 0; 348 label:; 349 } 350