1// RUN: %clang_analyze_cc1 -fblocks -fobjc-arc -verify %s -Wno-objc-root-class \ 2// RUN: -analyzer-checker=core \ 3// RUN: -analyzer-checker=alpha.core.StackAddressAsyncEscape \ 4// RUN: -analyzer-checker=nullability \ 5// RUN: -analyzer-checker=osx 6 7#include "Inputs/system-header-simulator-for-nullability.h" 8#include "os_object_base.h" 9 10struct OSIterator : public OSObject { 11 static const OSMetaClass * const metaClass; 12}; 13 14@interface TestObject : NSObject 15- (int *_Nonnull)returnsNonnull; 16- (int *_Nullable)returnsNullable; 17- (int *)returnsUnspecified; 18- (void)takesNonnull:(int *_Nonnull)p; 19- (void)takesNullable:(int *_Nullable)p; 20- (void)takesUnspecified:(int *)p; 21@property(readonly, strong) NSString *stuff; 22@end 23 24TestObject * getUnspecifiedTestObject(); 25TestObject *_Nonnull getNonnullTestObject(); 26TestObject *_Nullable getNullableTestObject(); 27 28int getRandom(); 29 30typedef struct Dummy { int val; } Dummy; 31 32void takesNullable(Dummy *_Nullable); 33void takesNonnull(Dummy *_Nonnull); 34void takesUnspecified(Dummy *); 35 36Dummy *_Nullable returnsNullable(); 37Dummy *_Nonnull returnsNonnull(); 38Dummy *returnsUnspecified(); 39int *_Nullable returnsNullableInt(); 40 41template <typename T> T *eraseNullab(T *p) { return p; } 42 43void takesAttrNonnull(Dummy *p) __attribute((nonnull(1))); 44 45void testBasicRules() { 46 // FIXME: None of these should be tied to a modeling checker. 47 Dummy *p = returnsNullable(); 48 int *ptr = returnsNullableInt(); 49 // Make every dereference a different path to avoid sinks after errors. 50 switch (getRandom()) { 51 case 0: { 52 Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}} 53 } break; 54 case 1: { 55 int b = p->val; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}} 56 } break; 57 case 2: { 58 int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}} 59 } break; 60 case 3: 61 takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter [nullability.NullablePassedToNonnull]}} 62 break; 63 case 4: { 64 Dummy d; 65 takesNullable(&d); 66 Dummy dd(d); 67 break; 68 } 69 case 5: 70 takesAttrNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null [nullability.NullableDereferenced]}} 71 break; 72 default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}} 73 } 74 if (p) { 75 takesNonnull(p); 76 if (getRandom()) { 77 Dummy &r = *p; 78 } else { 79 int b = p->val; 80 } 81 } 82 Dummy *q = 0; 83 if (getRandom()) { 84 takesNullable(q); 85 // FIXME: This shouldn't be tied to a modeling checker. 86 takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter [nullability.NullPassedToNonnull]}} 87 } 88 Dummy a; 89 Dummy *_Nonnull nonnull = &a; 90 // FIXME: This shouldn't be tied to a modeling checker. 91 nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value [nullability.NullPassedToNonnull]}} 92 q = &a; 93 takesNullable(q); 94 takesNonnull(q); 95} 96 97typedef int NSInteger; 98typedef struct _NSZone NSZone; 99@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 100@class NSDictionary; 101@interface NSError : NSObject <NSCopying, NSCoding> {} 102+ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict; 103@end 104 105struct __CFError {}; 106typedef struct __CFError* CFErrorRef; 107 108void foo(CFErrorRef* error) { // expected-warning{{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occurred [osx.coreFoundation.CFError]}} 109 // FIXME: This shouldn't be tied to a modeling checker. 110 *error = 0; // expected-warning {{Potential null dereference. According to coding standards documented in CoreFoundation/CFError.h the parameter may be null [osx.coreFoundation.CFError]}} 111} 112 113@interface A 114- (void)myMethodWhichMayFail:(NSError **)error; 115@end 116 117@implementation A 118- (void)myMethodWhichMayFail:(NSError **)error { // expected-warning {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occurred [osx.cocoa.NSError]}} 119 *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning {{Potential null dereference. According to coding standards in 'Creating and Returning NSError Objects' the parameter may be null [osx.cocoa.NSError]}} 120} 121@end 122 123bool write_into_out_param_on_success(OS_RETURNS_RETAINED OSObject **obj); 124 125void use_out_param_leak() { 126 OSObject *obj; 127 // FIXME: This shouldn't be tied to a modeling checker. 128 write_into_out_param_on_success(&obj); // expected-warning{{Potential leak of an object stored into 'obj' [osx.cocoa.RetainCount]}} 129} 130 131typedef struct dispatch_queue_s *dispatch_queue_t; 132typedef void (^dispatch_block_t)(void); 133void dispatch_async(dispatch_queue_t queue, dispatch_block_t block); 134typedef long dispatch_once_t; 135void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block); 136typedef long dispatch_time_t; 137void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block); 138void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); 139 140extern dispatch_queue_t queue; 141extern dispatch_once_t *predicate; 142extern dispatch_time_t when; 143 144dispatch_block_t get_leaking_block() { 145 int leaked_x = 791; 146 int *p = &leaked_x; 147 return ^void(void) { 148 *p = 1; 149 }; 150 // expected-warning@-3 {{Address of stack memory associated with local variable 'leaked_x' \ 151is captured by a returned block [core.StackAddressEscape]}} 152} 153 154void test_returned_from_func_block_async() { 155 dispatch_async(queue, get_leaking_block()); 156 // expected-warning@-1 {{Address of stack memory associated with local variable 'leaked_x' \ 157is captured by an asynchronously-executed block [alpha.core.StackAddressAsyncEscape]}} 158} 159