1 // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 %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 done on non-array variables means reliance 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}} expected-warning{{Pointer arithmetic done on non-array variables}} 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 clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{TRUE}} 217 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}} 218 219 if (lhs >= rhs) { 220 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{TRUE}} 221 return; 222 } 223 224 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 225 clang_analyzer_eval(lhs < rhs); // expected-warning{{TRUE}} 226 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}} 227 } 228 229 void size_implies_comparison(int *lhs, int *rhs) { 230 clang_analyzer_eval(lhs <= rhs); // expected-warning{{UNKNOWN}} 231 232 if ((rhs - lhs) < 0) { 233 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 234 return; 235 } 236 237 clang_analyzer_eval(lhs <= rhs); // expected-warning{{TRUE}} 238 clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{TRUE}} 239 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}} 240 241 if ((rhs - lhs) <= 0) { 242 clang_analyzer_eval(lhs == rhs); // expected-warning{{TRUE}} 243 return; 244 } 245 246 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 247 clang_analyzer_eval(lhs < rhs); // expected-warning{{TRUE}} 248 clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}} 249 } 250 251 //------------------------------- 252 // False positives 253 //------------------------------- 254 255 void zero_implies_reversed_equal(int *lhs, int *rhs) { 256 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}} 257 if ((rhs - lhs) == 0) { 258 // FIXME: Should be FALSE. 259 clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}} 260 // FIXME: Should be TRUE. 261 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 262 return; 263 } 264 clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}} 265 // FIXME: Should be FALSE. 266 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 267 // FIXME: Should be TRUE. 268 clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}} 269 } 270 271 void canonical_equal(int *lhs, int *rhs) { 272 clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}} 273 if (lhs == rhs) { 274 // FIXME: Should be TRUE. 275 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 276 return; 277 } 278 clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} 279 280 // FIXME: Should be FALSE. 281 clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} 282 } 283 284 void compare_element_region_and_base(int *p) { 285 int *q = p - 1; 286 clang_analyzer_eval(p == q); // expected-warning{{FALSE}} 287 } 288 289 struct Point { 290 int x; 291 int y; 292 }; 293 void symbolicFieldRegion(struct Point *points, int i, int j) { 294 clang_analyzer_eval(&points[i].x == &points[j].x);// expected-warning{{UNKNOWN}} 295 clang_analyzer_eval(&points[i].x == &points[i].y);// expected-warning{{FALSE}} 296 clang_analyzer_eval(&points[i].x < &points[i].y);// expected-warning{{TRUE}} 297 } 298 299