1 // RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s 2 // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyze -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s 3 4 typedef long unsigned int size_t; 5 void *memcpy(void *, const void *, size_t); 6 void *alloca(size_t); 7 8 typedef struct objc_selector *SEL; 9 typedef signed char BOOL; 10 typedef int NSInteger; 11 typedef unsigned int NSUInteger; 12 typedef struct _NSZone NSZone; 13 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 14 @protocol NSObject - (BOOL)isEqual:(id)object; @end 15 @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end 16 @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end 17 @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end 18 @interface NSObject <NSObject> {} - (id)init; @end 19 extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); 20 @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> 21 - (NSUInteger)length; 22 + (id)stringWithUTF8String:(const char *)nullTerminatedCString; 23 @end extern NSString * const NSBundleDidLoadNotification; 24 @interface NSAssertionHandler : NSObject {} 25 + (NSAssertionHandler *)currentHandler; 26 - (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...; 27 @end 28 extern NSString * const NSConnectionReplyMode; 29 30 #ifdef TEST_64 31 typedef long long int64_t; 32 typedef int64_t intptr_t; 33 #else 34 typedef int int32_t; 35 typedef int32_t intptr_t; 36 #endif 37 38 //--------------------------------------------------------------------------- 39 // Test case 'checkaccess_union' differs for region store and basic store. 40 // The basic store doesn't reason about compound literals, so the code 41 // below won't fire an "uninitialized value" warning. 42 //--------------------------------------------------------------------------- 43 44 // PR 2948 (testcase; crash on VisitLValue for union types) 45 // http://llvm.org/bugs/show_bug.cgi?id=2948 46 void checkaccess_union() { 47 int ret = 0, status; 48 // Since RegionStore doesn't handle unions yet, 49 // this branch condition won't be triggered 50 // as involving an uninitialized value. 51 if (((((__extension__ (((union { // no-warning 52 __typeof (status) __in; int __i;} 53 ) 54 { 55 .__in = (status)} 56 ).__i))) & 0xff00) >> 8) == 1) 57 ret = 1; 58 } 59 60 // Check our handling of fields being invalidated by function calls. 61 struct test2_struct { int x; int y; char* s; }; 62 void test2_help(struct test2_struct* p); 63 64 char test2() { 65 struct test2_struct s; 66 test2_help(&s); 67 char *p = 0; 68 69 if (s.x > 1) { 70 if (s.s != 0) { 71 p = "hello"; 72 } 73 } 74 75 if (s.x > 1) { 76 if (s.s != 0) { 77 return *p; 78 } 79 } 80 81 return 'a'; 82 } 83 84 // BasicStore handles this case incorrectly because it doesn't reason about 85 // the value pointed to by 'x' and thus creates different symbolic values 86 // at the declarations of 'a' and 'b' respectively. RegionStore handles 87 // it correctly. See the companion test in 'misc-ps-basic-store.m'. 88 void test_trivial_symbolic_comparison_pointer_parameter(int *x) { 89 int a = *x; 90 int b = *x; 91 if (a != b) { 92 int *p = 0; 93 *p = 0xDEADBEEF; // no-warning 94 } 95 } 96 97 // This is a modified test from 'misc-ps.m'. Here we have the extra 98 // NULL dereferences which are pruned out by RegionStore's symbolic reasoning 99 // of fields. 100 typedef struct _BStruct { void *grue; } BStruct; 101 void testB_aux(void *ptr); 102 103 void testB(BStruct *b) { 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 testB_aux(__gruep__); 114 } 115 { 116 int *__gruep__ = ((int *)&((b)->grue)); 117 int __gruev__ = *__gruep__; 118 int __gruev2__ = *__gruep__; 119 if (__gruev__ != __gruev2__) { 120 int *p = 0; 121 *p = 0xDEADBEEF; // no-warning 122 } 123 124 if (~0 != __gruev__) {} 125 } 126 } 127 128 void testB_2(BStruct *b) { 129 { 130 int **__gruep__ = ((int **)&((b)->grue)); 131 int *__gruev__ = *__gruep__; 132 testB_aux(__gruep__); 133 } 134 { 135 int **__gruep__ = ((int **)&((b)->grue)); 136 int *__gruev__ = *__gruep__; 137 if ((int*)~0 != __gruev__) {} 138 } 139 } 140 141 // This test case is a reduced case of a caching bug discovered by an 142 // assertion failure in RegionStoreManager::BindArray. Essentially the 143 // DeclStmt is evaluated twice, but on the second loop iteration the 144 // engine caches out. Previously a false transition would cause UnknownVal 145 // to bind to the variable, firing an assertion failure. This bug was fixed 146 // in r76262. 147 void test_declstmt_caching() { 148 again: 149 { 150 const char a[] = "I like to crash"; 151 goto again; 152 } 153 } 154 155 //===----------------------------------------------------------------------===// 156 // Reduced test case from <rdar://problem/7114618>. 157 // Basically a null check is performed on the field value, which is then 158 // assigned to a variable and then checked again. 159 //===----------------------------------------------------------------------===// 160 struct s_7114618 { int *p; }; 161 void test_rdar_7114618(struct s_7114618 *s) { 162 if (s->p) { 163 int *p = s->p; 164 if (!p) { 165 // Infeasible 166 int *dead = 0; 167 *dead = 0xDEADBEEF; // no-warning 168 } 169 } 170 } 171 172 // Test pointers increment correctly. 173 void f() { 174 int a[2]; 175 a[1] = 3; 176 int *p = a; 177 p++; 178 if (*p != 3) { 179 int *q = 0; 180 *q = 3; // no-warning 181 } 182 } 183 184 //===----------------------------------------------------------------------===// 185 // <rdar://problem/7185607> 186 // Bit-fields of a struct should be invalidated when blasting the entire 187 // struct with an integer constant. 188 //===----------------------------------------------------------------------===// 189 struct test_7185607 { 190 int x : 10; 191 int y : 22; 192 }; 193 int rdar_test_7185607() { 194 struct test_7185607 s; // Uninitialized. 195 *((unsigned *) &s) = 0U; 196 return s.x; // no-warning 197 } 198 199 //===----------------------------------------------------------------------===// 200 // <rdar://problem/7242006> [RegionStore] compound literal assignment with 201 // floats not honored 202 // This test case is mirrored in misc-ps.m, but this case is a negative. 203 //===----------------------------------------------------------------------===// 204 typedef float CGFloat; 205 typedef struct _NSSize { 206 CGFloat width; 207 CGFloat height; 208 } NSSize; 209 210 CGFloat rdar7242006_negative(CGFloat x) { 211 NSSize y; 212 return y.width; // expected-warning{{garbage}} 213 } 214 215 //===----------------------------------------------------------------------===// 216 // <rdar://problem/7249340> - Allow binding of values to symbolic regions. 217 // This test case shows how RegionStore tracks the value bound to 'x' 218 // after the assignment. 219 //===----------------------------------------------------------------------===// 220 typedef int* ptr_rdar_7249340; 221 void rdar_7249340(ptr_rdar_7249340 x) { 222 *x = 1; 223 if (*x) 224 return; 225 int *p = 0; // This is unreachable. 226 *p = 0xDEADBEEF; // no-warning 227 } 228 229 //===----------------------------------------------------------------------===// 230 // <rdar://problem/7249327> - This test case tests both value tracking of 231 // array values and that we handle symbolic values that are casted 232 // between different integer types. Note the assignment 'n = *a++'; here 233 // 'n' is and 'int' and '*a' is 'unsigned'. Previously we got a false positive 234 // at 'x += *b++' (undefined value) because we got a false path. 235 //===----------------------------------------------------------------------===// 236 int rdar_7249327_aux(void); 237 238 void rdar_7249327(unsigned int A[2*32]) { 239 int B[2*32]; 240 int *b; 241 unsigned int *a; 242 int x = 0; 243 244 int n; 245 246 a = A; 247 b = B; 248 249 n = *a++; 250 if (n) 251 *b++ = rdar_7249327_aux(); 252 253 a = A; 254 b = B; 255 256 n = *a++; 257 if (n) 258 x += *b++; // no-warning 259 } 260 261 //===----------------------------------------------------------------------===// 262 // <rdar://problem/6914474> - Check that 'x' is invalidated because its 263 // address is passed in as a value to a struct. 264 //===----------------------------------------------------------------------===// 265 struct doodad_6914474 { int *v; }; 266 extern void prod_6914474(struct doodad_6914474 *d); 267 int rdar_6914474(void) { 268 int x; 269 struct doodad_6914474 d; 270 d.v = &x; 271 prod_6914474(&d); 272 return x; // no-warning 273 } 274 275 // Test invalidation of a single field. 276 struct s_test_field_invalidate { 277 int x; 278 }; 279 extern void test_invalidate_field(int *x); 280 int test_invalidate_field_test() { 281 struct s_test_field_invalidate y; 282 test_invalidate_field(&y.x); 283 return y.x; // no-warning 284 } 285 int test_invalidate_field_test_positive() { 286 struct s_test_field_invalidate y; 287 return y.x; // expected-warning{{garbage}} 288 } 289 290 // This test case illustrates how a typeless array of bytes casted to a 291 // struct should be treated as initialized. RemoveDeadBindings previously 292 // had a bug that caused 'x' to lose its default symbolic value after the 293 // assignment to 'p', thus causing 'p->z' to evaluate to "undefined". 294 struct ArrayWrapper { unsigned char y[16]; }; 295 struct WrappedStruct { unsigned z; }; 296 297 void test_handle_array_wrapper_helper(); 298 299 int test_handle_array_wrapper() { 300 struct ArrayWrapper x; 301 test_handle_array_wrapper_helper(&x); 302 struct WrappedStruct *p = (struct WrappedStruct*) x.y; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}} 303 return p->z; // no-warning 304 } 305 306 //===----------------------------------------------------------------------===// 307 // <rdar://problem/7261075> [RegionStore] crash when 308 // handling load: '*((unsigned int *)"????")' 309 //===----------------------------------------------------------------------===// 310 311 int rdar_7261075(void) { 312 unsigned int var = 0; 313 if (var == *((unsigned int *)"????")) 314 return 1; 315 return 0; 316 } 317 318 //===----------------------------------------------------------------------===// 319 // <rdar://problem/7275774> false path due to limited pointer 320 // arithmetic constraints 321 //===----------------------------------------------------------------------===// 322 323 void rdar_7275774(void *data, unsigned n) { 324 if (!(data || n == 0)) 325 return; 326 327 unsigned short *p = (unsigned short*) data; 328 unsigned short *q = p + (n / 2); 329 330 if (p < q) { 331 // If we reach here, 'p' cannot be null. If 'p' is null, then 'n' must 332 // be '0', meaning that this branch is not feasible. 333 *p = *q; // no-warning 334 } 335 } 336 337 //===----------------------------------------------------------------------===// 338 // <rdar://problem/7312221> 339 // 340 // Test that Objective-C instance variables aren't prematurely pruned 341 // from the analysis state. 342 //===----------------------------------------------------------------------===// 343 344 struct rdar_7312221_value { int x; }; 345 346 @interface RDar7312221 347 { 348 struct rdar_7312221_value *y; 349 } 350 - (void) doSomething_7312221; 351 @end 352 353 extern struct rdar_7312221_value *rdar_7312221_helper(); 354 extern int rdar_7312221_helper_2(id o); 355 extern void rdar_7312221_helper_3(int z); 356 357 @implementation RDar7312221 358 - (void) doSomething_7312221 { 359 if (y == 0) { 360 y = rdar_7312221_helper(); 361 if (y != 0) { 362 y->x = rdar_7312221_helper_2(self); 363 // The following use of 'y->x' previously triggered a null dereference, as the value of 'y' 364 // before 'y = rdar_7312221_helper()' would be used. 365 rdar_7312221_helper_3(y->x); // no-warning 366 } 367 } 368 } 369 @end 370 371 struct rdar_7312221_container { 372 struct rdar_7312221_value *y; 373 }; 374 375 extern int rdar_7312221_helper_4(struct rdar_7312221_container *s); 376 377 // This test case essentially matches the one in [RDar7312221 doSomething_7312221]. 378 void doSomething_7312221_with_struct(struct rdar_7312221_container *Self) { 379 if (Self->y == 0) { 380 Self->y = rdar_7312221_helper(); 381 if (Self->y != 0) { 382 Self->y->x = rdar_7312221_helper_4(Self); 383 rdar_7312221_helper_3(Self->y->x); // no-warning 384 } 385 } 386 } 387 388 //===----------------------------------------------------------------------===// 389 // <rdar://problem/7332673> - Just more tests cases for regions 390 //===----------------------------------------------------------------------===// 391 392 void rdar_7332673_test1() { 393 char value[1]; 394 if ( *(value) != 1 ) {} // expected-warning{{The left operand of '!=' is a garbage value}} 395 } 396 int rdar_7332673_test2_aux(char *x); 397 void rdar_7332673_test2() { 398 char *value; 399 if ( rdar_7332673_test2_aux(value) != 1 ) {} // expected-warning{{Function call argument is an uninitialized value}} 400 } 401 402 //===----------------------------------------------------------------------===// 403 // <rdar://problem/7347252>: Because of a bug in 404 // RegionStoreManager::RemoveDeadBindings(), the symbol for s->session->p 405 // would incorrectly be pruned from the state after the call to 406 // rdar7347252_malloc1(), and would incorrectly result in a warning about 407 // passing a null pointer to rdar7347252_memcpy(). 408 //===----------------------------------------------------------------------===// 409 410 struct rdar7347252_AA { char *p;}; 411 typedef struct { 412 struct rdar7347252_AA *session; 413 int t; 414 char *q; 415 } rdar7347252_SSL1; 416 417 int rdar7347252_f(rdar7347252_SSL1 *s); 418 char *rdar7347252_malloc1(int); 419 char *rdar7347252_memcpy1(char *d, char *s, int n) __attribute__((nonnull (1,2))); 420 421 int rdar7347252(rdar7347252_SSL1 *s) { 422 rdar7347252_f(s); // the SymbolicRegion of 's' is set a default binding of conjured symbol 423 if (s->session->p == ((void*)0)) { 424 if ((s->session->p = rdar7347252_malloc1(10)) == ((void*)0)) { 425 return 0; 426 } 427 rdar7347252_memcpy1(s->session->p, "aa", 2); // no-warning 428 } 429 return 0; 430 } 431 432 //===----------------------------------------------------------------------===// 433 // PR 5316 - "crash when accessing field of lazy compound value" 434 // Previously this caused a crash at the MemberExpr '.chr' when loading 435 // a field value from a LazyCompoundVal 436 //===----------------------------------------------------------------------===// 437 438 typedef unsigned int pr5316_wint_t; 439 typedef pr5316_wint_t pr5316_REFRESH_CHAR; 440 typedef struct { 441 pr5316_REFRESH_CHAR chr; 442 } 443 pr5316_REFRESH_ELEMENT; 444 static void pr5316(pr5316_REFRESH_ELEMENT *dst, const pr5316_REFRESH_ELEMENT *src) { 445 while ((*dst++ = *src++).chr != L'\0') ; 446 } 447 448 //===----------------------------------------------------------------------===// 449 // Exercise creating ElementRegion with symbolic super region. 450 //===----------------------------------------------------------------------===// 451 void element_region_with_symbolic_superregion(int* p) { 452 int *x; 453 int a; 454 if (p[0] == 1) 455 x = &a; 456 if (p[0] == 1) 457 (void)*x; // no-warning 458 } 459 460 //===----------------------------------------------------------------------===// 461 // Test returning an out-of-bounds pointer (CWE-466) 462 //===----------------------------------------------------------------------===// 463 464 static int test_cwe466_return_outofbounds_pointer_a[10]; 465 int *test_cwe466_return_outofbounds_pointer() { 466 int *p = test_cwe466_return_outofbounds_pointer_a+10; 467 return p; // expected-warning{{Returned pointer value points outside the original object}} 468 } 469 470 //===----------------------------------------------------------------------===// 471 // PR 3135 - Test case that shows that a variable may get invalidated when its 472 // address is included in a structure that is passed-by-value to an unknown function. 473 //===----------------------------------------------------------------------===// 474 475 typedef struct { int *a; } pr3135_structure; 476 int pr3135_bar(pr3135_structure *x); 477 int pr3135() { 478 int x; 479 pr3135_structure y = { &x }; 480 // the call to pr3135_bar may initialize x 481 if (pr3135_bar(&y) && x) // no-warning 482 return 1; 483 return 0; 484 } 485 486 //===----------------------------------------------------------------------===// 487 // <rdar://problem/7403269> - Test that we handle compound initializers with 488 // partially unspecified array values. Previously this caused a crash. 489 //===----------------------------------------------------------------------===// 490 491 typedef struct RDar7403269 { 492 unsigned x[10]; 493 unsigned y; 494 } RDar7403269; 495 496 void rdar7403269() { 497 RDar7403269 z = { .y = 0 }; 498 if (z.x[4] == 0) 499 return; 500 int *p = 0; 501 *p = 0xDEADBEEF; // no-warning 502 } 503 504 typedef struct RDar7403269_b { 505 struct zorg { int w; int k; } x[10]; 506 unsigned y; 507 } RDar7403269_b; 508 509 void rdar7403269_b() { 510 RDar7403269_b z = { .y = 0 }; 511 if (z.x[5].w == 0) 512 return; 513 int *p = 0; 514 *p = 0xDEADBEEF; // no-warning 515 } 516 517 void rdar7403269_b_pos() { 518 RDar7403269_b z = { .y = 0 }; 519 if (z.x[5].w == 1) 520 return; 521 int *p = 0; 522 *p = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}} 523 } 524 525 526 //===----------------------------------------------------------------------===// 527 // Test that incrementing a non-null pointer results in a non-null pointer. 528 // (<rdar://problem/7191542>) 529 //===----------------------------------------------------------------------===// 530 531 void test_increment_nonnull_rdar_7191542(const char *path) { 532 const char *alf = 0; 533 534 for (;;) { 535 // When using basic-store, we get a null dereference here because we lose information 536 // about path after the pointer increment. 537 char c = *path++; // no-warning 538 if (c == 'a') { 539 alf = path; 540 } 541 542 if (alf) 543 return; 544 } 545 } 546 547 //===----------------------------------------------------------------------===// 548 // Test that the store (implicitly) tracks values for doubles/floats that are 549 // uninitialized (<rdar://problem/6811085>) 550 //===----------------------------------------------------------------------===// 551 552 double rdar_6811085(void) { 553 double u; 554 return u + 10; // expected-warning{{The left operand of '+' is a garbage value}} 555 } 556 557 //===----------------------------------------------------------------------===// 558 // Path-sensitive tests for blocks. 559 //===----------------------------------------------------------------------===// 560 561 void indirect_block_call(void (^f)()); 562 563 int blocks_1(int *p, int z) { 564 __block int *q = 0; 565 void (^bar)() = ^{ q = p; }; 566 567 if (z == 1) { 568 // The call to 'bar' might cause 'q' to be invalidated. 569 bar(); 570 *q = 0x1; // no-warning 571 } 572 else if (z == 2) { 573 // The function 'indirect_block_call' might invoke bar, thus causing 574 // 'q' to possibly be invalidated. 575 indirect_block_call(bar); 576 *q = 0x1; // no-warning 577 } 578 else { 579 *q = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}} 580 } 581 return z; 582 } 583 584 int blocks_2(int *p, int z) { 585 int *q = 0; 586 void (^bar)(int **) = ^(int **r){ *r = p; }; 587 588 if (z) { 589 // The call to 'bar' might cause 'q' to be invalidated. 590 bar(&q); 591 *q = 0x1; // no-warning 592 } 593 else { 594 *q = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}} 595 } 596 return z; 597 } 598 599 // Test that the value of 'x' is considered invalidated after the block 600 // is passed as an argument to the message expression. 601 typedef void (^RDar7582031CB)(void); 602 @interface RDar7582031 603 - rdar7582031:RDar7582031CB; 604 - rdar7582031_b:RDar7582031CB; 605 @end 606 607 // Test with one block. 608 unsigned rdar7582031(RDar7582031 *o) { 609 __block unsigned x; 610 [o rdar7582031:^{ x = 1; }]; 611 return x; // no-warning 612 } 613 614 // Test with two blocks. 615 unsigned long rdar7582031_b(RDar7582031 *o) { 616 __block unsigned y; 617 __block unsigned long x; 618 [o rdar7582031:^{ y = 1; }]; 619 [o rdar7582031_b:^{ x = 1LL; }]; 620 return x + (unsigned long) y; // no-warning 621 } 622 623 // Show we get an error when 'o' is null because the message 624 // expression has no effect. 625 unsigned long rdar7582031_b2(RDar7582031 *o) { 626 __block unsigned y; 627 __block unsigned long x; 628 if (o) 629 return 1; 630 [o rdar7582031:^{ y = 1; }]; 631 [o rdar7582031_b:^{ x = 1LL; }]; 632 return x + (unsigned long) y; // expected-warning{{The left operand of '+' is a garbage value}} 633 } 634 635 // Show that we handle static variables also getting invalidated. 636 void rdar7582031_aux(void (^)(void)); 637 RDar7582031 *rdar7582031_aux_2(); 638 639 unsigned rdar7582031_static() { 640 static RDar7582031 *o = 0; 641 rdar7582031_aux(^{ o = rdar7582031_aux_2(); }); 642 643 __block unsigned x; 644 [o rdar7582031:^{ x = 1; }]; 645 return x; // no-warning 646 } 647 648 //===----------------------------------------------------------------------===// 649 // <rdar://problem/7462324> - Test that variables passed using __blocks 650 // are not treated as being uninitialized. 651 //===----------------------------------------------------------------------===// 652 653 typedef void (^RDar_7462324_Callback)(id obj); 654 655 @interface RDar7462324 656 - (void) foo:(id)target; 657 - (void) foo_positive:(id)target; 658 659 @end 660 661 @implementation RDar7462324 662 - (void) foo:(id)target { 663 __block RDar_7462324_Callback builder = ((void*) 0); 664 builder = ^(id object) { 665 if (object) { 666 builder(self); // no-warning 667 } 668 }; 669 builder(target); 670 } 671 - (void) foo_positive:(id)target { 672 __block RDar_7462324_Callback builder = ((void*) 0); 673 builder = ^(id object) { 674 id x; 675 if (object) { 676 builder(x); // expected-warning{{Block call argument is an uninitialized value}} 677 } 678 }; 679 builder(target); 680 } 681 @end 682 683 //===----------------------------------------------------------------------===// 684 // <rdar://problem/7468209> - Scanning for live variables within a block should 685 // not crash on variables passed by reference via __block. 686 //===----------------------------------------------------------------------===// 687 688 int rdar7468209_aux(); 689 void rdar7468209_aux_2(); 690 691 void rdar7468209() { 692 __block int x = 0; 693 ^{ 694 x = rdar7468209_aux(); 695 // We need a second statement so that 'x' would be removed from the store if it wasn't 696 // passed by reference. 697 rdar7468209_aux_2(); 698 }(); 699 } 700 701 //===----------------------------------------------------------------------===// 702 // PR 5857 - Test loading an integer from a byte array that has also been 703 // reinterpreted to be loaded as a field. 704 //===----------------------------------------------------------------------===// 705 706 typedef struct { int x; } TestFieldLoad; 707 int pr5857(char *src) { 708 TestFieldLoad *tfl = (TestFieldLoad *) (intptr_t) src; 709 int y = tfl->x; 710 long long *z = (long long *) (intptr_t) src; 711 long long w = 0; 712 int n = 0; 713 for (n = 0; n < y; ++n) { 714 // Previously we crashed analyzing this statement. 715 w = *z++; 716 } 717 return 1; 718 } 719 720 //===----------------------------------------------------------------------===// 721 // PR 4358 - Without field-sensitivity, this code previously triggered 722 // a false positive that 'uninit' could be uninitialized at the call 723 // to pr4358_aux(). 724 //===----------------------------------------------------------------------===// 725 726 struct pr4358 { 727 int bar; 728 int baz; 729 }; 730 void pr4358_aux(int x); 731 void pr4358(struct pr4358 *pnt) { 732 int uninit; 733 if (pnt->bar < 3) { 734 uninit = 1; 735 } else if (pnt->baz > 2) { 736 uninit = 3; 737 } else if (pnt->baz <= 2) { 738 uninit = 2; 739 } 740 pr4358_aux(uninit); // no-warning 741 } 742 743 //===----------------------------------------------------------------------===// 744 // <rdar://problem/7526777> 745 // Test handling fields of values returned from function calls or 746 // message expressions. 747 //===----------------------------------------------------------------------===// 748 749 typedef struct testReturn_rdar_7526777 { 750 int x; 751 int y; 752 } testReturn_rdar_7526777; 753 754 @interface TestReturnStruct_rdar_7526777 755 - (testReturn_rdar_7526777) foo; 756 @end 757 758 int test_return_struct(TestReturnStruct_rdar_7526777 *x) { 759 return [x foo].x; 760 } 761 762 testReturn_rdar_7526777 test_return_struct_2_aux_rdar_7526777(); 763 764 int test_return_struct_2_rdar_7526777() { 765 return test_return_struct_2_aux_rdar_7526777().x; 766 } 767 768 //===----------------------------------------------------------------------===// 769 // <rdar://problem/7527292> Assertion failed: (Op == BinaryOperator::Add || 770 // Op == BinaryOperator::Sub) 771 // This test case previously triggered an assertion failure due to a discrepancy 772 // been the loaded/stored value in the array 773 //===----------------------------------------------------------------------===// 774 775 _Bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__theValue ); 776 777 void rdar_7527292() { 778 static id Cache7527292[32]; 779 for (signed long idx = 0; 780 idx < 32; 781 idx++) { 782 id v = Cache7527292[idx]; 783 if (v && OSAtomicCompareAndSwapPtrBarrier(v, ((void*)0), (void * volatile *)(Cache7527292 + idx))) { 784 } 785 } 786 } 787 788 //===----------------------------------------------------------------------===// 789 // <rdar://problem/7515938> - Handle initialization of incomplete arrays 790 // in structures using a compound value. Previously this crashed. 791 //===----------------------------------------------------------------------===// 792 793 struct rdar_7515938 { 794 int x; 795 int y[]; 796 }; 797 798 const struct rdar_7515938 *rdar_7515938() { 799 static const struct rdar_7515938 z = { 0, { 1, 2 } }; 800 if (z.y[0] != 1) { 801 int *p = 0; 802 *p = 0xDEADBEEF; // no-warning 803 } 804 return &z; 805 } 806 807 struct rdar_7515938_str { 808 int x; 809 char y[]; 810 }; 811 812 const struct rdar_7515938_str *rdar_7515938_str() { 813 static const struct rdar_7515938_str z = { 0, "hello" }; 814 return &z; 815 } 816 817 //===----------------------------------------------------------------------===// 818 // Assorted test cases from PR 4172. 819 //===----------------------------------------------------------------------===// 820 821 struct PR4172A_s { int *a; }; 822 823 void PR4172A_f2(struct PR4172A_s *p); 824 825 int PR4172A_f1(void) { 826 struct PR4172A_s m; 827 int b[4]; 828 m.a = b; 829 PR4172A_f2(&m); 830 return b[3]; // no-warning 831 } 832 833 struct PR4172B_s { int *a; }; 834 835 void PR4172B_f2(struct PR4172B_s *p); 836 837 int PR4172B_f1(void) { 838 struct PR4172B_s m; 839 int x; 840 m.a = &x; 841 PR4172B_f2(&m); 842 return x; // no-warning 843 } 844 845 //===----------------------------------------------------------------------===// 846 // Test invalidation of values in struct literals. 847 //===----------------------------------------------------------------------===// 848 849 struct s_rev96062 { int *x; int *y; }; 850 struct s_rev96062_nested { struct s_rev96062 z; }; 851 852 void test_a_rev96062_aux(struct s_rev96062 *s); 853 void test_a_rev96062_aux2(struct s_rev96062_nested *s); 854 855 int test_a_rev96062() { 856 int a, b; 857 struct s_rev96062 x = { &a, &b }; 858 test_a_rev96062_aux(&x); 859 return a + b; // no-warning 860 } 861 int test_b_rev96062() { 862 int a, b; 863 struct s_rev96062 x = { &a, &b }; 864 struct s_rev96062 z = x; 865 test_a_rev96062_aux(&z); 866 return a + b; // no-warning 867 } 868 int test_c_rev96062() { 869 int a, b; 870 struct s_rev96062 x = { &a, &b }; 871 struct s_rev96062_nested w = { x }; 872 struct s_rev96062_nested z = w; 873 test_a_rev96062_aux2(&z); 874 return a + b; // no-warning 875 } 876 877 //===----------------------------------------------------------------------===// 878 // <rdar://problem/7242010> - The access to y[0] at the bottom previously 879 // was reported as an uninitialized value. 880 //===----------------------------------------------------------------------===// 881 882 char *rdar_7242010(int count, char **y) { 883 char **x = alloca((count + 4) * sizeof(*x)); 884 x[0] = "hi"; 885 x[1] = "there"; 886 x[2] = "every"; 887 x[3] = "body"; 888 memcpy(x + 4, y, count * sizeof(*x)); 889 y = x; 890 return y[0]; // no-warning 891 } 892 893 //===----------------------------------------------------------------------===// 894 // <rdar://problem/7770737> 895 //===----------------------------------------------------------------------===// 896 897 struct rdar_7770737_s { intptr_t p; }; 898 void rdar_7770737_aux(struct rdar_7770737_s *p); 899 int rdar_7770737(void) 900 { 901 int x; 902 903 // Previously 'f' was not properly invalidated, causing the use of 904 // an uninitailized value below. 905 struct rdar_7770737_s f = { .p = (intptr_t)&x }; 906 rdar_7770737_aux(&f); 907 return x; // no-warning 908 } 909 int rdar_7770737_pos(void) 910 { 911 int x; 912 struct rdar_7770737_s f = { .p = (intptr_t)&x }; 913 return x; // expected-warning{{Undefined or garbage value returned to caller}} 914 } 915 916 //===----------------------------------------------------------------------===// 917 // Test handling of the implicit 'isa' field. For now we don't do anything 918 // interesting. 919 //===----------------------------------------------------------------------===// 920 921 void pr6302(id x, Class y) { 922 // This previously crashed the analyzer (reported in PR 6302) 923 x->isa = y; // expected-warning {{assignment to Objective-C's isa is deprecated in favor of object_setClass()}} 924 } 925 926 //===----------------------------------------------------------------------===// 927 // Specially handle global variables that are declared constant. In the 928 // example below, this forces the loop to take exactly 2 iterations. 929 //===----------------------------------------------------------------------===// 930 931 const int pr6288_L_N = 2; 932 void pr6288_(void) { 933 int x[2]; 934 int *px[2]; 935 int i; 936 for (i = 0; i < pr6288_L_N; i++) 937 px[i] = &x[i]; 938 *(px[0]) = 0; // no-warning 939 } 940 941 void pr6288_pos(int z) { 942 int x[2]; 943 int *px[2]; 944 int i; 945 for (i = 0; i < z; i++) 946 px[i] = &x[i]; // expected-warning{{Access out-of-bound array element (buffer overflow)}} 947 *(px[0]) = 0; // expected-warning{{Dereference of undefined pointer value}} 948 } 949 950 void pr6288_b(void) { 951 const int L_N = 2; 952 int x[2]; 953 int *px[2]; 954 int i; 955 for (i = 0; i < L_N; i++) 956 px[i] = &x[i]; 957 *(px[0]) = 0; // no-warning 958 } 959 960 // <rdar://problem/7817800> - A bug in RemoveDeadBindings was causing instance variable bindings 961 // to get prematurely pruned from the state. 962 @interface Rdar7817800 { 963 char *x; 964 } 965 - (void) rdar7817800_baz; 966 @end 967 968 char *rdar7817800_foobar(); 969 void rdar7817800_qux(void*); 970 971 @implementation Rdar7817800 972 - (void) rdar7817800_baz { 973 if (x) 974 rdar7817800_qux(x); 975 x = rdar7817800_foobar(); 976 // Previously this triggered a bogus null dereference warning. 977 x[1] = 'a'; // no-warning 978 } 979 @end 980 981 // PR 6036 - This test case triggered a crash inside StoreManager::CastRegion because the size 982 // of 'unsigned long (*)[0]' is 0. 983 struct pr6036_a { int pr6036_b; }; 984 struct pr6036_c; 985 void u132monitk (struct pr6036_c *pr6036_d) { 986 (void) ((struct pr6036_a *) (unsigned long (*)[0]) ((char *) pr6036_d - 1))->pr6036_b; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}} 987 } 988 989 // <rdar://problem/7813989> - ?-expressions used as a base of a member expression should be treated as an lvalue 990 typedef struct rdar7813989_NestedVal { int w; } rdar7813989_NestedVal; 991 typedef struct rdar7813989_Val { rdar7813989_NestedVal nv; } rdar7813989_Val; 992 993 int rdar7813989(int x, rdar7813989_Val *a, rdar7813989_Val *b) { 994 // This previously crashed with an assertion failure. 995 int z = (x ? a->nv : b->nv).w; 996 return z + 1; 997 } 998 999 // PR 6844 - Don't crash on vaarg expression. 1000 typedef __builtin_va_list va_list; 1001 void map(int srcID, ...) { 1002 va_list ap; 1003 int i; 1004 for (i = 0; i < srcID; i++) { 1005 int v = __builtin_va_arg(ap, int); 1006 } 1007 } 1008 1009 // PR 6854 - crash when casting symbolic memory address to a float 1010 // Handle casting from a symbolic region to a 'float'. This isn't 1011 // really all that intelligent, but previously this caused a crash 1012 // in SimpleSValuator. 1013 void pr6854(void * arg) { 1014 void * a = arg; 1015 *(void**)a = arg; 1016 float f = *(float*) a; 1017 } 1018 1019 // <rdar://problem/8032791> False positive due to symbolic store not find 1020 // value because of 'const' qualifier 1021 double rdar_8032791_2(); 1022 double rdar_8032791_1() { 1023 struct R8032791 { double x[2]; double y; } 1024 data[3] = { 1025 {{1.0, 3.0}, 3.0}, // 1 2 3 1026 {{1.0, 1.0}, 0.0}, // 1 1 2 2 3 3 1027 {{1.0, 3.0}, 1.0} // 1 2 3 1028 }; 1029 1030 double x = 0.0; 1031 for (unsigned i = 0 ; i < 3; i++) { 1032 const struct R8032791 *p = &data[i]; 1033 x += p->y + rdar_8032791_2(); // no-warning 1034 } 1035 return x; 1036 } 1037 1038 // PR 7450 - Handle pointer arithmetic with __builtin_alloca 1039 void pr_7450_aux(void *x); 1040 void pr_7450() { 1041 void *p = __builtin_alloca(10); 1042 // Don't crash when analyzing the following statement. 1043 pr_7450_aux(p + 8); 1044 } 1045 1046 // <rdar://problem/8243408> - Symbolicate struct values returned by value. 1047 struct s_rdar_8243408 { int x; }; 1048 extern struct s_rdar_8243408 rdar_8243408_aux(void); 1049 void rdar_8243408(void) { 1050 struct s_rdar_8243408 a = { 1 }, *b = 0; 1051 while (a.x && !b) 1052 a = rdar_8243408_aux(); 1053 1054 // Previously there was a false error here with 'b' being null. 1055 (void) (a.x && b->x); // no-warning 1056 1057 // Introduce a null deref to ensure we are checking this path. 1058 int *p = 0; 1059 *p = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}} 1060 } 1061 1062 // <rdar://problem/8258814> 1063 int r8258814() 1064 { 1065 int foo; 1066 int * a = &foo; 1067 a[0] = 10; 1068 // Do not warn that the value of 'foo' is uninitialized. 1069 return foo; // no-warning 1070 } 1071 1072 // PR 8052 - Don't crash when reasoning about loads from a function address.\n 1073 typedef unsigned int __uint32_t; 1074 typedef unsigned long vm_offset_t; 1075 typedef __uint32_t pd_entry_t; 1076 typedef unsigned char u_char; 1077 typedef unsigned int u_int; 1078 typedef unsigned long u_long; 1079 extern int bootMP_size; 1080 void bootMP(void); 1081 static void 1082 pr8052(u_int boot_addr) 1083 { 1084 int x; 1085 int size = *(int *) ((u_long) & bootMP_size); 1086 u_char *src = (u_char *) ((u_long) bootMP); 1087 u_char *dst = (u_char *) boot_addr + ((vm_offset_t) ((((((((1 << 1088 12) / (sizeof(pd_entry_t))) - 1) - 1) - (260 - 2))) << 22) | ((0) << 12))); 1089 #ifdef TEST_64 1090 // expected-warning@-3 {{cast to 'u_char *' (aka 'unsigned char *') from smaller integer type 'u_int' (aka 'unsigned int')}} 1091 #endif 1092 for (x = 0; 1093 x < size; 1094 ++x) 1095 *dst++ = *src++; 1096 } 1097 1098 // PR 8015 - don't return undefined values for arrays when using a valid 1099 // symbolic index 1100 int pr8015_A(); 1101 void pr8015_B(const char *); 1102 1103 void pr8015_C() { 1104 int number = pr8015_A(); 1105 const char *numbers[] = { "zero" }; 1106 if (number == 0) { 1107 pr8015_B(numbers[number]); // no-warning 1108 } 1109 } 1110 1111 // Tests that we correctly handle that 'number' is perfectly constrained 1112 // after 'if (nunber == 0)', allowing us to resolve that 1113 // numbers[number] == numbers[0]. 1114 void pr8015_D_FIXME() { 1115 int number = pr8015_A(); 1116 const char *numbers[] = { "zero" }; 1117 if (number == 0) { 1118 if (numbers[number] == numbers[0]) 1119 return; 1120 // Unreachable. 1121 int *p = 0; 1122 *p = 0xDEADBEEF; // no-warnng 1123 } 1124 } 1125 1126 void pr8015_E() { 1127 // Similar to pr8015_C, but number is allowed to be a valid range. 1128 unsigned number = pr8015_A(); 1129 const char *numbers[] = { "zero", "one", "two" }; 1130 if (number < 3) { 1131 pr8015_B(numbers[number]); // no-warning 1132 } 1133 } 1134 1135 void pr8015_F_FIXME() { 1136 // Similar to pr8015_E, but like pr8015_D we check if the pointer 1137 // is the same as one of the string literals. The null dereference 1138 // here is not feasible in practice, so this is a false positive. 1139 int number = pr8015_A(); 1140 const char *numbers[] = { "zero", "one", "two" }; 1141 if (number < 3) { 1142 const char *p = numbers[number]; 1143 if (p == numbers[0] || p == numbers[1] || p == numbers[2]) 1144 return; 1145 int *q = 0; 1146 *q = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}} 1147 } 1148 } 1149 1150 // PR 8141. Previously the statement expression in the for loop caused 1151 // the CFG builder to crash. 1152 struct list_pr8141 1153 { 1154 struct list_pr8141 *tail; 1155 }; 1156 1157 struct list_pr8141 * 1158 pr8141 (void) { 1159 struct list_pr8141 *items; 1160 for (;; items = ({ do { } while (0); items->tail; })) // expected-warning{{Dereference of undefined pointer value}} 1161 { 1162 } 1163 } 1164 1165 // Don't crash when building the CFG. 1166 void do_not_crash(int x) { 1167 while (x - ({do {} while (0); x; })) { 1168 } 1169 } 1170 1171 // <rdar://problem/8424269> - Handle looking at the size of a VLA in 1172 // ArrayBoundChecker. Nothing intelligent (yet); just don't crash. 1173 typedef struct RDar8424269_A { 1174 int RDar8424269_C; 1175 } RDar8424269_A; 1176 static void RDar8424269_B(RDar8424269_A *p, unsigned char *RDar8424269_D, 1177 const unsigned char *RDar8424269_E, int RDar8424269_F, 1178 int b_w, int b_h, int dx, int dy) { 1179 int x, y, b, r, l; 1180 unsigned char tmp2t[3][RDar8424269_F * (32 + 8)]; 1181 unsigned char *tmp2 = tmp2t[0]; 1182 if (p && !p->RDar8424269_C) 1183 b = 15; 1184 tmp2 = tmp2t[1]; 1185 if (b & 2) { // expected-warning{{The left operand of '&' is a garbage value}} 1186 for (y = 0; y < b_h; y++) { 1187 for (x = 0; x < b_w + 1; x++) { 1188 int am = 0; 1189 tmp2[x] = am; 1190 } 1191 } 1192 } 1193 tmp2 = tmp2t[2]; 1194 } 1195 1196 // <rdar://problem/8642434> - Handle transparent unions with the NonNullParamChecker. 1197 typedef union { 1198 struct rdar_8642434_typeA *_dq; 1199 } 1200 rdar_8642434_typeB __attribute__((transparent_union)); 1201 1202 __attribute__((visibility("default"))) __attribute__((__nonnull__)) __attribute__((__nothrow__)) 1203 void rdar_8642434_funcA(rdar_8642434_typeB object); 1204 1205 void rdar_8642434_funcB(struct rdar_8642434_typeA *x, struct rdar_8642434_typeA *y) { 1206 rdar_8642434_funcA(x); 1207 if (!y) 1208 rdar_8642434_funcA(y); // expected-warning{{Null pointer passed as an argument to a 'nonnull' parameter}} 1209 } 1210 1211 // <rdar://problem/8848957> - Handle loads and stores from a symbolic index 1212 // into array without warning about an uninitialized value being returned. 1213 // While RegionStore can't fully reason about this example, it shouldn't 1214 // warn here either. 1215 typedef struct s_test_rdar8848957 { 1216 int x, y, z; 1217 } s_test_rdar8848957; 1218 1219 s_test_rdar8848957 foo_rdar8848957(); 1220 int rdar8848957(int index) { 1221 s_test_rdar8848957 vals[10]; 1222 vals[index] = foo_rdar8848957(); 1223 return vals[index].x; // no-warning 1224 } 1225 1226 // PR 9049 - crash on symbolicating unions. This test exists solely to 1227 // test that the analyzer doesn't crash. 1228 typedef struct pr9048_cdev *pr9048_cdev_t; 1229 typedef union pr9048_abstracted_disklabel { void *opaque; } pr9048_disklabel_t; 1230 struct pr9048_diskslice { pr9048_disklabel_t ds_label; }; 1231 struct pr9048_diskslices { 1232 int dss_secmult; 1233 struct pr9048_diskslice dss_slices[16]; 1234 }; 1235 void pr9048(pr9048_cdev_t dev, struct pr9048_diskslices * ssp, unsigned int slice) 1236 { 1237 pr9048_disklabel_t lp; 1238 struct pr9048_diskslice *sp; 1239 sp = &ssp->dss_slices[slice]; 1240 if (ssp->dss_secmult == 1) { 1241 } else if ((lp = sp->ds_label).opaque != ((void *) 0)) { 1242 } 1243 } 1244 1245 // Test Store reference counting in the presence of Lazy compound values. 1246 // This previously caused an infinite recursion. 1247 typedef struct {} Rdar_9103310_A; 1248 typedef struct Rdar_9103310_B Rdar_9103310_B_t; 1249 struct Rdar_9103310_B { 1250 unsigned char Rdar_9103310_C[101]; 1251 }; 1252 void Rdar_9103310_E(Rdar_9103310_A * x, struct Rdar_9103310_C * b) { // expected-warning {{declaration of 'struct Rdar_9103310_C' will not be visible outside of this function}} 1253 char Rdar_9103310_D[4][4] = { "a", "b", "c", "d"}; 1254 int i; 1255 Rdar_9103310_B_t *y = (Rdar_9103310_B_t *) x; 1256 for (i = 0; i < 101; i++) { 1257 Rdar_9103310_F(b, "%2d%s ", (y->Rdar_9103310_C[i]) / 4, Rdar_9103310_D[(y->Rdar_9103310_C[i]) % 4]); // expected-warning {{implicit declaration of function 'Rdar_9103310_F' is invalid in C99}} 1258 } 1259 } 1260 1261 // Test handling binding lazy compound values to a region and then have 1262 // specific elements have other bindings. 1263 int PR9455() { 1264 char arr[4] = "000"; 1265 arr[0] = '1'; 1266 if (arr[1] == '0') 1267 return 1; 1268 int *p = 0; 1269 *p = 0xDEADBEEF; // no-warning 1270 return 1; 1271 } 1272 int PR9455_2() { 1273 char arr[4] = "000"; 1274 arr[0] = '1'; 1275 if (arr[1] == '0') { 1276 int *p = 0; 1277 *p = 0xDEADBEEF; // expected-warning {{null}} 1278 } 1279 return 1; 1280 } 1281 1282 // Test initialization of substructs via lazy compound values. 1283 typedef float RDar9163742_Float; 1284 1285 typedef struct { 1286 RDar9163742_Float x, y; 1287 } RDar9163742_Point; 1288 typedef struct { 1289 RDar9163742_Float width, height; 1290 } RDar9163742_Size; 1291 typedef struct { 1292 RDar9163742_Point origin; 1293 RDar9163742_Size size; 1294 } RDar9163742_Rect; 1295 1296 extern RDar9163742_Rect RDar9163742_RectIntegral(RDar9163742_Rect); 1297 1298 RDar9163742_Rect RDar9163742_IntegralRect(RDar9163742_Rect frame) 1299 { 1300 RDar9163742_Rect integralFrame; 1301 integralFrame.origin.x = frame.origin.x; 1302 integralFrame.origin.y = frame.origin.y; 1303 integralFrame.size = frame.size; 1304 return RDar9163742_RectIntegral(integralFrame); // no-warning; all fields initialized 1305 } 1306 1307 // Test correct handling of prefix '--' operator. 1308 void rdar9444714() { 1309 int x; 1310 char str[ 32 ]; 1311 char buf[ 32 ]; 1312 char * dst; 1313 char * ptr; 1314 1315 x = 1234; 1316 dst = str; 1317 ptr = buf; 1318 do 1319 { 1320 *ptr++ = (char)( '0' + ( x % 10 ) ); 1321 x /= 10; 1322 } while( x > 0 ); 1323 1324 while( ptr > buf ) 1325 { 1326 *dst++ = *( --( ptr ) ); // no-warning 1327 } 1328 *dst = '\0'; 1329 } 1330 1331 // Test handling symbolic elements with field accesses. 1332 // <rdar://problem/11127008> 1333 typedef struct { 1334 unsigned value; 1335 } RDar11127008; 1336 1337 signed rdar_11127008_index(); 1338 1339 static unsigned rdar_11127008(void) { 1340 RDar11127008 values[] = {{.value = 0}, {.value = 1}}; 1341 signed index = rdar_11127008_index(); 1342 if (index < 0) return 0; 1343 if (index >= 2) return 0; 1344 return values[index].value; 1345 } 1346 1347 // Test handling invalidating arrays passed to a block via captured 1348 // pointer value (not a __block variable). 1349 typedef void (^radar11125868_cb)(int *, unsigned); 1350 1351 void rdar11125868_aux(radar11125868_cb cb); 1352 1353 int rdar11125868() { 1354 int integersStackArray[1]; 1355 int *integers = integersStackArray; 1356 rdar11125868_aux(^(int *integerValue, unsigned index) { 1357 integers[index] = integerValue[index]; 1358 }); 1359 return integers[0] == 0; // no-warning 1360 } 1361 1362 int rdar11125868_positive() { 1363 int integersStackArray[1]; 1364 int *integers = integersStackArray; 1365 return integers[0] == 0; // expected-warning {{The left operand of '==' is a}} 1366 } 1367