misc-ps-region-store.m revision 4fcfde4d5c8f25e40720972a5543d538a0dcb220
1// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s 2// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s 3 4typedef struct objc_selector *SEL; 5typedef signed char BOOL; 6typedef int NSInteger; 7typedef unsigned int NSUInteger; 8typedef struct _NSZone NSZone; 9@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 10@protocol NSObject - (BOOL)isEqual:(id)object; @end 11@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end 12@protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end 13@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end 14@interface NSObject <NSObject> {} - (id)init; @end 15extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); 16@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> 17- (NSUInteger)length; 18+ (id)stringWithUTF8String:(const char *)nullTerminatedCString; 19@end extern NSString * const NSBundleDidLoadNotification; 20@interface NSAssertionHandler : NSObject {} 21+ (NSAssertionHandler *)currentHandler; 22- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...; 23@end 24extern NSString * const NSConnectionReplyMode; 25 26 27//--------------------------------------------------------------------------- 28// Test case 'checkaccess_union' differs for region store and basic store. 29// The basic store doesn't reason about compound literals, so the code 30// below won't fire an "uninitialized value" warning. 31//--------------------------------------------------------------------------- 32 33// PR 2948 (testcase; crash on VisitLValue for union types) 34// http://llvm.org/bugs/show_bug.cgi?id=2948 35void checkaccess_union() { 36 int ret = 0, status; 37 // Since RegionStore doesn't handle unions yet, 38 // this branch condition won't be triggered 39 // as involving an uninitialized value. 40 if (((((__extension__ (((union { // no-warning 41 __typeof (status) __in; int __i;} 42 ) 43 { 44 .__in = (status)} 45 ).__i))) & 0xff00) >> 8) == 1) 46 ret = 1; 47} 48 49// Check our handling of fields being invalidated by function calls. 50struct test2_struct { int x; int y; char* s; }; 51void test2_helper(struct test2_struct* p); 52 53char test2() { 54 struct test2_struct s; 55 test2_help(&s); 56 char *p = 0; 57 58 if (s.x > 1) { 59 if (s.s != 0) { 60 p = "hello"; 61 } 62 } 63 64 if (s.x > 1) { 65 if (s.s != 0) { 66 return *p; 67 } 68 } 69 70 return 'a'; 71} 72 73// BasicStore handles this case incorrectly because it doesn't reason about 74// the value pointed to by 'x' and thus creates different symbolic values 75// at the declarations of 'a' and 'b' respectively. RegionStore handles 76// it correctly. See the companion test in 'misc-ps-basic-store.m'. 77void test_trivial_symbolic_comparison_pointer_parameter(int *x) { 78 int a = *x; 79 int b = *x; 80 if (a != b) { 81 int *p = 0; 82 *p = 0xDEADBEEF; // no-warning 83 } 84} 85 86// This is a modified test from 'misc-ps.m'. Here we have the extra 87// NULL dereferences which are pruned out by RegionStore's symbolic reasoning 88// of fields. 89typedef struct _BStruct { void *grue; } BStruct; 90void testB_aux(void *ptr); 91 92void testB(BStruct *b) { 93 { 94 int *__gruep__ = ((int *)&((b)->grue)); 95 int __gruev__ = *__gruep__; 96 int __gruev2__ = *__gruep__; 97 if (__gruev__ != __gruev2__) { 98 int *p = 0; 99 *p = 0xDEADBEEF; // no-warning 100 } 101 102 testB_aux(__gruep__); 103 } 104 { 105 int *__gruep__ = ((int *)&((b)->grue)); 106 int __gruev__ = *__gruep__; 107 int __gruev2__ = *__gruep__; 108 if (__gruev__ != __gruev2__) { 109 int *p = 0; 110 *p = 0xDEADBEEF; // no-warning 111 } 112 113 if (~0 != __gruev__) {} 114 } 115} 116 117void testB_2(BStruct *b) { 118 { 119 int **__gruep__ = ((int **)&((b)->grue)); 120 int *__gruev__ = *__gruep__; 121 testB_aux(__gruep__); 122 } 123 { 124 int **__gruep__ = ((int **)&((b)->grue)); 125 int *__gruev__ = *__gruep__; 126 if ((int*)~0 != __gruev__) {} 127 } 128} 129 130// This test case is a reduced case of a caching bug discovered by an 131// assertion failure in RegionStoreManager::BindArray. Essentially the 132// DeclStmt is evaluated twice, but on the second loop iteration the 133// engine caches out. Previously a false transition would cause UnknownVal 134// to bind to the variable, firing an assertion failure. This bug was fixed 135// in r76262. 136void test_declstmt_caching() { 137again: 138 { 139 const char a[] = "I like to crash"; 140 goto again; 141 } 142} 143 144//===----------------------------------------------------------------------===// 145// Reduced test case from <rdar://problem/7114618>. 146// Basically a null check is performed on the field value, which is then 147// assigned to a variable and then checked again. 148//===----------------------------------------------------------------------===// 149struct s_7114618 { int *p; }; 150void test_rdar_7114618(struct s_7114618 *s) { 151 if (s->p) { 152 int *p = s->p; 153 if (!p) { 154 // Infeasible 155 int *dead = 0; 156 *dead = 0xDEADBEEF; // no-warning 157 } 158 } 159} 160 161// Test pointers increment correctly. 162void f() { 163 int a[2]; 164 a[1] = 3; 165 int *p = a; 166 p++; 167 if (*p != 3) { 168 int *q = 0; 169 *q = 3; // no-warning 170 } 171} 172 173//===----------------------------------------------------------------------===// 174// <rdar://problem/7185607> 175// Bit-fields of a struct should be invalidated when blasting the entire 176// struct with an integer constant. 177//===----------------------------------------------------------------------===// 178struct test_7185607 { 179 int x : 10; 180 int y : 22; 181}; 182int rdar_test_7185607() { 183 struct test_7185607 s; // Uninitialized. 184 *((unsigned *) &s) = 0U; 185 return s.x; // no-warning 186} 187 188//===----------------------------------------------------------------------===// 189// <rdar://problem/7242006> [RegionStore] compound literal assignment with 190// floats not honored 191// This test case is mirrored in misc-ps.m, but this case is a negative. 192//===----------------------------------------------------------------------===// 193typedef float CGFloat; 194typedef struct _NSSize { 195 CGFloat width; 196 CGFloat height; 197} NSSize; 198 199CGFloat rdar7242006_negative(CGFloat x) { 200 NSSize y; 201 return y.width; // expected-warning{{garbage}} 202} 203 204//===----------------------------------------------------------------------===// 205// <rdar://problem/7249340> - Allow binding of values to symbolic regions. 206// This test case shows how RegionStore tracks the value bound to 'x' 207// after the assignment. 208//===----------------------------------------------------------------------===// 209typedef int* ptr_rdar_7249340; 210void rdar_7249340(ptr_rdar_7249340 x) { 211 *x = 1; 212 if (*x) 213 return; 214 int *p = 0; // This is unreachable. 215 *p = 0xDEADBEEF; // no-warning 216} 217 218//===----------------------------------------------------------------------===// 219// <rdar://problem/7249327> - This test case tests both value tracking of 220// array values and that we handle symbolic values that are casted 221// between different integer types. Note the assignment 'n = *a++'; here 222// 'n' is and 'int' and '*a' is 'unsigned'. Previously we got a false positive 223// at 'x += *b++' (undefined value) because we got a false path. 224//===----------------------------------------------------------------------===// 225int rdar_7249327_aux(void); 226 227void rdar_7249327(unsigned int A[2*32]) { 228 int B[2*32]; 229 int *b; 230 unsigned int *a; 231 int x = 0; 232 233 int n; 234 235 a = A; 236 b = B; 237 238 n = *a++; 239 if (n) 240 *b++ = rdar_7249327_aux(); 241 242 a = A; 243 b = B; 244 245 n = *a++; 246 if (n) 247 x += *b++; // no-warning 248} 249 250//===----------------------------------------------------------------------===// 251// <rdar://problem/6914474> - Check that 'x' is invalidated because its 252// address is passed in as a value to a struct. 253//===----------------------------------------------------------------------===// 254struct doodad_6914474 { int *v; }; 255extern void prod_6914474(struct doodad_6914474 *d); 256int rdar_6914474(void) { 257 int x; 258 struct doodad_6914474 d; 259 d.v = &x; 260 prod_6914474(&d); 261 return x; // no-warning 262} 263 264// Test invalidation of a single field. 265struct s_test_field_invalidate { 266 int x; 267}; 268extern void test_invalidate_field(int *x); 269int test_invalidate_field_test() { 270 struct s_test_field_invalidate y; 271 test_invalidate_field(&y.x); 272 return y.x; // no-warning 273} 274int test_invalidate_field_test_positive() { 275 struct s_test_field_invalidate y; 276 return y.x; // expected-warning{{garbage}} 277} 278 279// This test case illustrates how a typeless array of bytes casted to a 280// struct should be treated as initialized. RemoveDeadBindings previously 281// had a bug that caused 'x' to lose its default symbolic value after the 282// assignment to 'p', thus causing 'p->z' to evaluate to "undefined". 283struct ArrayWrapper { unsigned char y[16]; }; 284struct WrappedStruct { unsigned z; }; 285 286int test_handle_array_wrapper() { 287 struct ArrayWrapper x; 288 test_handle_array_wrapper(&x); 289 struct WrappedStruct *p = (struct WrappedStruct*) x.y; 290 return p->z; // no-warning 291} 292 293//===----------------------------------------------------------------------===// 294// <rdar://problem/7261075> [RegionStore] crash when 295// handling load: '*((unsigned int *)"????")' 296//===----------------------------------------------------------------------===// 297 298int rdar_7261075(void) { 299 unsigned int var = 0; 300 if (var == *((unsigned int *)"????")) 301 return 1; 302 return 0; 303} 304 305//===----------------------------------------------------------------------===// 306// <rdar://problem/7275774> false path due to limited pointer 307// arithmetic constraints 308//===----------------------------------------------------------------------===// 309 310void rdar_7275774(void *data, unsigned n) { 311 if (!(data || n == 0)) 312 return; 313 314 unsigned short *p = (unsigned short*) data; 315 unsigned short *q = p + (n / 2); 316 317 if (p < q) { 318 // If we reach here, 'p' cannot be null. If 'p' is null, then 'n' must 319 // be '0', meaning that this branch is not feasible. 320 *p = *q; // no-warning 321 } 322} 323 324//===----------------------------------------------------------------------===// 325// <rdar://problem/7312221> 326// 327// Test that Objective-C instance variables aren't prematurely pruned 328// from the analysis state. 329//===----------------------------------------------------------------------===// 330 331struct rdar_7312221_value { int x; }; 332 333@interface RDar7312221 334{ 335 struct rdar_7312221_value *y; 336} 337- (void) doSomething_7312221; 338@end 339 340extern struct rdar_7312221_value *rdar_7312221_helper(); 341extern int rdar_7312221_helper_2(id o); 342extern void rdar_7312221_helper_3(int z); 343 344@implementation RDar7312221 345- (void) doSomething_7312221 { 346 if (y == 0) { 347 y = rdar_7312221_helper(); 348 if (y != 0) { 349 y->x = rdar_7312221_helper_2(self); 350 // The following use of 'y->x' previously triggered a null dereference, as the value of 'y' 351 // before 'y = rdar_7312221_helper()' would be used. 352 rdar_7312221_helper_3(y->x); // no-warning 353 } 354 } 355} 356@end 357 358struct rdar_7312221_container { 359 struct rdar_7312221_value *y; 360}; 361 362extern int rdar_7312221_helper_4(struct rdar_7312221_container *s); 363 364// This test case essentially matches the one in [RDar7312221 doSomething_7312221]. 365void doSomething_7312221_with_struct(struct rdar_7312221_container *Self) { 366 if (Self->y == 0) { 367 Self->y = rdar_7312221_helper(); 368 if (Self->y != 0) { 369 Self->y->x = rdar_7312221_helper_4(Self); 370 rdar_7312221_helper_3(Self->y->x); // no-warning 371 } 372 } 373} 374 375//===----------------------------------------------------------------------===// 376// <rdar://problem/7332673> - Just more tests cases for regions 377//===----------------------------------------------------------------------===// 378 379void rdar_7332673_test1() { 380 char value[1]; 381 if ( *(value) != 1 ) {} // expected-warning{{The left operand of '!=' is a garbage value}} 382} 383void rdar_rdar_7332673_test2_aux(char *x); 384void rdar_7332673_test2() { 385 char *value; 386 if ( rdar_7332673_test2_aux(value) != 1 ) {} // expected-warning{{Pass-by-value argument in function call is undefined}} 387} 388 389//===----------------------------------------------------------------------===// 390// <rdar://problem/7347252>: Because of a bug in 391// RegionStoreManager::RemoveDeadBindings(), the symbol for s->session->p 392// would incorrectly be pruned from the state after the call to 393// rdar7347252_malloc1(), and would incorrectly result in a warning about 394// passing a null pointer to rdar7347252_memcpy(). 395//===----------------------------------------------------------------------===// 396 397struct rdar7347252_AA { char *p;}; 398typedef struct { 399 struct rdar7347252_AA *session; 400 int t; 401 char *q; 402} rdar7347252_SSL1; 403 404int rdar7347252_f(rdar7347252_SSL1 *s); 405char *rdar7347252_malloc1(int); 406char *rdar7347252_memcpy1(char *d, char *s, int n) __attribute__((nonnull (1,2))); 407 408int rdar7347252(rdar7347252_SSL1 *s) { 409 rdar7347252_f(s); // the SymbolicRegion of 's' is set a default binding of conjured symbol 410 if (s->session->p == ((void*)0)) { 411 if ((s->session->p = rdar7347252_malloc1(10)) == ((void*)0)) { 412 return 0; 413 } 414 rdar7347252_memcpy1(s->session->p, "aa", 2); // no-warning 415 } 416 return 0; 417} 418 419//===----------------------------------------------------------------------===// 420// PR 5316 - "crash when accessing field of lazy compound value" 421// Previously this caused a crash at the MemberExpr '.chr' when loading 422// a field value from a LazyCompoundVal 423//===----------------------------------------------------------------------===// 424 425typedef unsigned int pr5316_wint_t; 426typedef pr5316_wint_t pr5316_REFRESH_CHAR; 427typedef struct { 428 pr5316_REFRESH_CHAR chr; 429} 430pr5316_REFRESH_ELEMENT; 431static void pr5316(pr5316_REFRESH_ELEMENT *dst, const pr5316_REFRESH_ELEMENT *src) { 432 while ((*dst++ = *src++).chr != L'\0') ; 433} 434 435//===----------------------------------------------------------------------===// 436// Exercise creating ElementRegion with symbolic super region. 437//===----------------------------------------------------------------------===// 438void element_region_with_symbolic_superregion(int* p) { 439 int *x; 440 int a; 441 if (p[0] == 1) 442 x = &a; 443 if (p[0] == 1) 444 (void)*x; // no-warning 445} 446 447//===----------------------------------------------------------------------===// 448// Test returning an out-of-bounds pointer (CWE-466) 449//===----------------------------------------------------------------------===// 450 451static int test_cwe466_return_outofbounds_pointer_a[10]; 452int *test_cwe466_return_outofbounds_pointer() { 453 int *p = test_cwe466_return_outofbounds_pointer_a+10; 454 return p; // expected-warning{{Returned pointer value points outside the original object}} 455} 456 457//===----------------------------------------------------------------------===// 458// PR 3135 - Test case that shows that a variable may get invalidated when its 459// address is included in a structure that is passed-by-value to an unknown function. 460//===----------------------------------------------------------------------===// 461 462typedef struct { int *a; } pr3135_structure; 463int pr3135_bar(pr3135_structure *x); 464int pr3135() { 465 int x; 466 pr3135_structure y = { &x }; 467 // the call to pr3135_bar may initialize x 468 if (pr3135_bar(&y) && x) // no-warning 469 return 1; 470 return 0; 471} 472 473