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