1// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \ 2// RUN: -analyzer-checker=nullability.NullPassedToNonnull \ 3// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull \ 4// RUN: -analyzer-checker=nullability.NullablePassedToNonnull \ 5// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull \ 6// RUN: -analyzer-checker=nullability.NullableDereferenced \ 7// RUN: -DNOSYSTEMHEADERS=0 8 9// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \ 10// RUN: -analyzer-checker=nullability.NullPassedToNonnull \ 11// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull \ 12// RUN: -analyzer-checker=nullability.NullablePassedToNonnull \ 13// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull \ 14// RUN: -analyzer-checker=nullability.NullableDereferenced \ 15// RUN: -DNOSYSTEMHEADERS=1 \ 16// RUN: -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true 17 18// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\ 19// RUN: -analyzer-checker=nullability.NullPassedToNonnull\ 20// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull\ 21// RUN: -analyzer-checker=nullability.NullablePassedToNonnull\ 22// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull\ 23// RUN: -analyzer-checker=nullability.NullableDereferenced\ 24// RUN: -DNOSYSTEMHEADERS=0 -fobjc-arc 25 26// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\ 27// RUN: -analyzer-checker=nullability.NullPassedToNonnull\ 28// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull\ 29// RUN: -analyzer-checker=nullability.NullablePassedToNonnull\ 30// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull\ 31// RUN: -analyzer-checker=nullability.NullableDereferenced\ 32// RUN: -DNOSYSTEMHEADERS=1 -fobjc-arc\ 33// RUN: -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true 34 35#include "Inputs/system-header-simulator-for-nullability.h" 36 37@interface TestObject : NSObject 38- (int *_Nonnull)returnsNonnull; 39- (int *_Nullable)returnsNullable; 40- (int *)returnsUnspecified; 41- (void)takesNonnull:(int *_Nonnull)p; 42- (void)takesNullable:(int *_Nullable)p; 43- (void)takesUnspecified:(int *)p; 44@property(readonly, strong) NSString *stuff; 45@end 46 47TestObject * getUnspecifiedTestObject(); 48TestObject *_Nonnull getNonnullTestObject(); 49TestObject *_Nullable getNullableTestObject(); 50 51int getRandom(); 52 53typedef struct Dummy { int val; } Dummy; 54 55void takesNullable(Dummy *_Nullable); 56void takesNonnull(Dummy *_Nonnull); 57void takesUnspecified(Dummy *); 58 59Dummy *_Nullable returnsNullable(); 60Dummy *_Nonnull returnsNonnull(); 61Dummy *returnsUnspecified(); 62int *_Nullable returnsNullableInt(); 63 64template <typename T> T *eraseNullab(T *p) { return p; } 65 66void takesAttrNonnull(Dummy *p) __attribute((nonnull(1))); 67 68void testBasicRules() { 69 Dummy *p = returnsNullable(); 70 int *ptr = returnsNullableInt(); 71 // Make every dereference a different path to avoid sinks after errors. 72 switch (getRandom()) { 73 case 0: { 74 Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced}} 75 } break; 76 case 1: { 77 int b = p->val; // expected-warning {{Nullable pointer is dereferenced}} 78 } break; 79 case 2: { 80 int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced}} 81 } break; 82 case 3: 83 takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 84 break; 85 case 4: { 86 Dummy d; 87 takesNullable(&d); 88 Dummy dd(d); 89 break; 90 } 91 case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}} 92 default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}} 93 } 94 if (p) { 95 takesNonnull(p); 96 if (getRandom()) { 97 Dummy &r = *p; 98 } else { 99 int b = p->val; 100 } 101 } 102 Dummy *q = 0; 103 if (getRandom()) { 104 takesNullable(q); 105 takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}} 106 } 107 Dummy a; 108 Dummy *_Nonnull nonnull = &a; 109 nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}} 110 q = &a; 111 takesNullable(q); 112 takesNonnull(q); 113} 114 115void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b, 116 Dummy *_Nonnull c); 117 118void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) { 119 Dummy *p = nullable; 120 Dummy *q = nonnull; 121 switch(getRandom()) { 122 case 1: nonnull = p; break; // expected-warning {{Nullable pointer is assigned to a pointer which is expected to have non-null value}} 123 case 2: p = 0; break; 124 case 3: q = p; break; 125 case 4: testMultiParamChecking(nonnull, nullable, nonnull); break; 126 case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break; 127 case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}} 128 case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 129 case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 130 case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break; 131 } 132} 133 134Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) { 135 Dummy *p = a; 136 return p; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}} 137} 138 139Dummy *_Nonnull testNullReturn() { 140 Dummy *p = 0; 141 return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}} 142} 143 144void testObjCMessageResultNullability() { 145 // The expected result: the most nullable of self and method return type. 146 TestObject *o = getUnspecifiedTestObject(); 147 int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull]; 148 switch (getRandom()) { 149 case 0: 150 // The core analyzer assumes that the receiver is non-null after a message 151 // send. This is to avoid some false positives, and increase performance 152 // but it also reduces the coverage and makes this checker unable to reason 153 // about the nullness of the receiver. 154 [o takesNonnull:shouldBeNullable]; // No warning expected. 155 break; 156 case 1: 157 shouldBeNullable = 158 [eraseNullab(getNullableTestObject()) returnsUnspecified]; 159 [o takesNonnull:shouldBeNullable]; // No warning expected. 160 break; 161 case 3: 162 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable]; 163 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 164 break; 165 case 4: 166 shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable]; 167 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 168 break; 169 case 5: 170 shouldBeNullable = 171 [eraseNullab(getUnspecifiedTestObject()) returnsNullable]; 172 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 173 break; 174 case 6: 175 shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable]; 176 [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 177 break; 178 case 7: { 179 int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull]; 180 [o takesNonnull:shouldBeNonnull]; 181 } break; 182 } 183} 184 185Dummy * _Nonnull testDirectCastNullableToNonnull() { 186 Dummy *p = returnsNullable(); 187 takesNonnull((Dummy * _Nonnull)p); // no-warning 188 return (Dummy * _Nonnull)p; // no-warning 189} 190 191Dummy * _Nonnull testIndirectCastNullableToNonnull() { 192 Dummy *p = (Dummy * _Nonnull)returnsNullable(); 193 takesNonnull(p); // no-warning 194 return p; // no-warning 195} 196 197Dummy * _Nonnull testDirectCastNilToNonnull() { 198 takesNonnull((Dummy * _Nonnull)0); // no-warning 199 return (Dummy * _Nonnull)0; // no-warning 200} 201 202void testIndirectCastNilToNonnullAndPass() { 203 Dummy *p = (Dummy * _Nonnull)0; 204 // FIXME: Ideally the cast above would suppress this warning. 205 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}} 206} 207 208void testDirectCastNilToNonnullAndAssignToLocalInInitializer() { 209 Dummy * _Nonnull nonnullLocalWithAssignmentInInitializer = (Dummy * _Nonnull)0; // no-warning 210 (void)nonnullLocalWithAssignmentInInitializer; 211 212 // Since we've already had an invariant violation along this path, 213 // we shouldn't warn here. 214 nonnullLocalWithAssignmentInInitializer = 0; 215 (void)nonnullLocalWithAssignmentInInitializer; 216 217} 218 219void testDirectCastNilToNonnullAndAssignToLocal(Dummy * _Nonnull p) { 220 Dummy * _Nonnull nonnullLocalWithAssignment = p; 221 nonnullLocalWithAssignment = (Dummy * _Nonnull)0; // no-warning 222 (void)nonnullLocalWithAssignment; 223 224 // Since we've already had an invariant violation along this path, 225 // we shouldn't warn here. 226 nonnullLocalWithAssignment = 0; 227 (void)nonnullLocalWithAssignment; 228} 229 230void testDirectCastNilToNonnullAndAssignToParam(Dummy * _Nonnull p) { 231 p = (Dummy * _Nonnull)0; // no-warning 232} 233 234@interface ClassWithNonnullIvar : NSObject { 235 Dummy *_nonnullIvar; 236} 237@end 238 239@implementation ClassWithNonnullIvar 240-(void)testDirectCastNilToNonnullAndAssignToIvar { 241 _nonnullIvar = (Dummy * _Nonnull)0; // no-warning; 242 243 // Since we've already had an invariant violation along this path, 244 // we shouldn't warn here. 245 _nonnullIvar = 0; 246} 247@end 248 249void testIndirectNilPassToNonnull() { 250 Dummy *p = 0; 251 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}} 252} 253 254void testConditionalNilPassToNonnull(Dummy *p) { 255 if (!p) { 256 takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}} 257 } 258} 259 260Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() { 261 Dummy *p = (Dummy * _Nonnull)0; 262 // FIXME: Ideally the cast above would suppress this warning. 263 return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}} 264} 265 266void testInvalidPropagation() { 267 Dummy *p = returnsUnspecified(); 268 takesNullable(p); 269 takesNonnull(p); 270} 271 272void onlyReportFirstPreconditionViolationOnPath() { 273 Dummy *p = returnsNullable(); 274 takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 275 takesNonnull(p); // No warning. 276 // The first warning was not a sink. The analysis expected to continue. 277 int i = 0; 278 i = 5 / i; // expected-warning {{Division by zero}} 279 (void)i; 280} 281 282Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc( 283 Dummy *_Nonnull p) { 284 if (!p) { 285 Dummy *ret = 286 0; // avoid compiler warning (which is not generated by the analyzer) 287 if (getRandom()) 288 return ret; // no warning 289 else 290 return p; // no warning 291 } else { 292 return p; 293 } 294} 295 296Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) { 297 if (!p) { 298 Dummy *ret = 299 0; // avoid compiler warning (which is not generated by the analyzer) 300 if (getRandom()) 301 return ret; // no warning 302 else 303 return p; // no warning 304 } else { 305 return p; 306 } 307} 308 309void testPreconditionViolationInInlinedFunction(Dummy *p) { 310 doNotWarnWhenPreconditionIsViolated(p); 311} 312 313@interface TestInlinedPreconditionViolationClass : NSObject 314@end 315 316@implementation TestInlinedPreconditionViolationClass 317-(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 { 318 Dummy *x = 0; 319 if (!p2) // p2 binding becomes dead at this point. 320 return x; // no-warning 321 else 322 return p2; 323} 324 325-(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 { 326 return [self calleeWithParam:p1]; 327} 328 329@end 330 331int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) { 332 int *x = 0; 333 if (!p2) // p2 binding becomes dead at this point. 334 return x; // no-warning 335 else 336 return p2; 337} 338 339int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) { 340 int *result = 0; 341 return result; // no-warning; but this is an over suppression 342} 343 344int *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) { 345 return InlinedReturnNullOverSuppressionCallee(p1); 346} 347 348void inlinedNullable(Dummy *_Nullable p) { 349 if (p) return; 350} 351void inlinedNonnull(Dummy *_Nonnull p) { 352 if (p) return; 353} 354void inlinedUnspecified(Dummy *p) { 355 if (p) return; 356} 357 358void testNilReturnWithBlock(Dummy *p) { 359 p = 0; 360 Dummy *_Nonnull (^myblock)(void) = ^Dummy *_Nonnull(void) { 361 return p; // TODO: We should warn in blocks. 362 }; 363 myblock(); 364} 365 366Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) { 367 switch (getRandom()) { 368 case 1: inlinedNullable(p); break; 369 case 2: inlinedNonnull(p); break; 370 case 3: inlinedUnspecified(p); break; 371 } 372 if (getRandom()) 373 takesNonnull(p); // no-warning 374 375 if (getRandom()) { 376 Dummy *_Nonnull varWithInitializer = p; // no-warning 377 378 Dummy *_Nonnull var1WithInitializer = p, // no-warning 379 *_Nonnull var2WithInitializer = p; // no-warning 380 } 381 382 if (getRandom()) { 383 Dummy *_Nonnull varWithoutInitializer; 384 varWithoutInitializer = p; // no-warning 385 } 386 387 return p; 388} 389 390 391@interface SomeClass : NSObject { 392 int instanceVar; 393} 394@end 395 396@implementation SomeClass (MethodReturn) 397- (id)initWithSomething:(int)i { 398 if (self = [super init]) { 399 instanceVar = i; 400 } 401 402 return self; 403} 404 405- (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly { 406 TestObject *local = getNullableTestObject(); 407 return local; // expected-warning {{Nullable pointer is returned from a method that is expected to return a non-null value}} 408} 409 410- (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly { 411 TestObject *local = getNullableTestObject(); 412 return (TestObject * _Nonnull)local; // no-warning 413} 414 415- (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p { 416 TestObject *local = getNullableTestObject(); 417 if (!p) // Pre-condition violated here. 418 return local; // no-warning 419 else 420 return p; // no-warning 421} 422@end 423 424@interface ClassWithInitializers : NSObject 425@end 426 427@implementation ClassWithInitializers 428- (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom { 429 // This defensive check is a common-enough idiom that we filter don't want 430 // to issue a diagnostic for it, 431 if (self = [super init]) { 432 } 433 434 return self; // no-warning 435} 436 437- (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal { 438 self = [super init]; 439 // This leaks, but we're not checking for that here. 440 441 ClassWithInitializers *other = nil; 442 // False negative. Once we have more subtle suppression of defensive checks in 443 // initializers we should warn here. 444 return other; 445} 446@end 447 448@interface SubClassWithInitializers : ClassWithInitializers 449@end 450 451@implementation SubClassWithInitializers 452// Note: Because this is overriding 453// -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom], 454// the return type of this method becomes implicitly id _Nonnull. 455- (id)initWithNonnullReturnAndSelfCheckingIdiom { 456 if (self = [super initWithNonnullReturnAndSelfCheckingIdiom]) { 457 } 458 459 return self; // no-warning 460} 461 462- (id _Nonnull)initWithNonnullReturnAndSelfCheckingIdiomV2; { 463 // Another common return-checking idiom 464 self = [super initWithNonnullReturnAndSelfCheckingIdiom]; 465 if (!self) { 466 return nil; // no-warning 467 } 468 469 return self; 470} 471@end 472 473@interface ClassWithCopyWithZone : NSObject<NSCopying,NSMutableCopying> { 474 id i; 475} 476 477@end 478 479@implementation ClassWithCopyWithZone 480-(id)copyWithZone:(NSZone *)zone { 481 ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init]; 482 if (!newInstance) 483 return nil; 484 485 newInstance->i = i; 486 return newInstance; 487} 488 489-(id)mutableCopyWithZone:(NSZone *)zone { 490 ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init]; 491 if (newInstance) { 492 newInstance->i = i; 493 } 494 495 return newInstance; 496} 497@end 498 499NSString * _Nullable returnsNullableString(); 500 501void callFunctionInSystemHeader() { 502 NSString *s = returnsNullableString(); 503 504 NSSystemFunctionTakingNonnull(s); 505 #if !NOSYSTEMHEADERS 506 // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 507 #endif 508} 509 510void callMethodInSystemHeader() { 511 NSString *s = returnsNullableString(); 512 513 NSSystemClass *sc = [[NSSystemClass alloc] init]; 514 [sc takesNonnull:s]; 515 #if !NOSYSTEMHEADERS 516 // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} 517 #endif 518} 519 520// Test to make sure the analyzer doesn't warn when an a nullability invariant 521// has already been found to be violated on an instance variable. 522 523@class MyInternalClass; 524@interface MyClass : NSObject { 525 MyInternalClass * _Nonnull _internal; 526} 527@end 528 529@interface MyInternalClass : NSObject { 530 @public 531 id _someIvar; 532} 533-(id _Nonnull)methodWithInternalImplementation; 534@end 535 536@interface MyClass () { 537 MyInternalClass * _Nonnull _nilledOutInternal; 538} 539@end 540 541@implementation MyClass 542-(id _Nonnull)methodWithInternalImplementation { 543 if (!_internal) 544 return nil; // no-warning 545 546 return [_internal methodWithInternalImplementation]; 547} 548 549- (id _Nonnull)methodReturningIvarInImplementation; { 550 return _internal == 0 ? nil : _internal->_someIvar; // no-warning 551} 552 553-(id _Nonnull)methodWithNilledOutInternal { 554 _nilledOutInternal = (id _Nonnull)nil; 555 556 return nil; // no-warning 557} 558@end 559