1 // RUN: %clang_analyze_cc1 -analyzer-checker=osx.SecKeychainAPI -fblocks %s -verify
3 #include "Inputs/system-header-simulator-objc.h"
6 typedef unsigned int OSStatus;
7 typedef unsigned int SecKeychainAttributeList;
8 typedef unsigned int SecKeychainItemRef;
9 typedef unsigned int SecItemClass;
10 typedef unsigned int UInt32;
11 typedef unsigned int SecProtocolType;
12 typedef unsigned int SecAuthenticationType;
13 typedef unsigned int SecKeychainAttributeInfo;
19 // Functions that allocate data.
20 OSStatus SecKeychainItemCopyContent (
21 SecKeychainItemRef itemRef,
22 SecItemClass *itemClass,
23 SecKeychainAttributeList *attrList,
27 OSStatus SecKeychainFindGenericPassword (
28 CFTypeRef keychainOrArray,
29 UInt32 serviceNameLength,
30 const char *serviceName,
31 UInt32 accountNameLength,
32 const char *accountName,
33 UInt32 *passwordLength,
35 SecKeychainItemRef *itemRef
37 OSStatus SecKeychainFindInternetPassword (
38 CFTypeRef keychainOrArray,
39 UInt32 serverNameLength,
40 const char *serverName,
41 UInt32 securityDomainLength,
42 const char *securityDomain,
43 UInt32 accountNameLength,
44 const char *accountName,
48 SecProtocolType protocol,
49 SecAuthenticationType authenticationType,
50 UInt32 *passwordLength,
52 SecKeychainItemRef *itemRef
54 OSStatus SecKeychainItemCopyAttributesAndData (
55 SecKeychainItemRef itemRef,
56 SecKeychainAttributeInfo *info,
57 SecItemClass *itemClass,
58 SecKeychainAttributeList **attrList,
63 // Functions which free data.
64 OSStatus SecKeychainItemFreeContent (
65 SecKeychainAttributeList *attrList,
68 OSStatus SecKeychainItemFreeAttributesAndData (
69 SecKeychainAttributeList *attrList,
73 void errRetVal(void) {
74 unsigned int *ptr = 0;
78 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
79 if (st == GenericError)
80 SecKeychainItemFreeContent(ptr, outData);
81 } // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
83 // If null is passed in, the data is not allocated, so no need for the matching free.
84 void fooDoNotReportNull(void) {
85 unsigned int *ptr = 0;
89 SecKeychainItemCopyContent(2, ptr, ptr, 0, 0);
90 SecKeychainItemCopyContent(2, ptr, ptr, length, outData);
93 void doubleAlloc(void) {
94 unsigned int *ptr = 0;
98 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
99 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); // expected-warning {{Allocated data should be released before another call to the allocator:}}
101 SecKeychainItemFreeContent(ptr, outData);
104 // Do not warn if undefined value is passed to a function.
105 void fooOnlyFreeUndef(void) {
106 unsigned int *ptr = 0;
110 SecKeychainItemFreeContent(ptr, outData);
113 // Do not warn if the address is a parameter in the enclosing function.
114 void fooOnlyFreeParam(void *attrList, void* X) {
115 SecKeychainItemFreeContent(attrList, X);
118 // If we are returning the value, do not report.
119 void* returnContent(void) {
120 unsigned int *ptr = 0;
124 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
128 // Password was passed in as an argument and does not have to be deleted.
129 OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) {
131 SecKeychainItemRef item;
132 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
133 passwordLength, password, &item);
137 // Make sure we do not report an error if we call free only if password != 0.
138 // Also, do not report double allocation if first allocation returned an error.
139 OSStatus testSecKeychainFindGenericPassword(UInt32* passwordLength,
140 CFTypeRef keychainOrArray, SecProtocolType protocol,
141 SecAuthenticationType authenticationType) {
143 SecKeychainItemRef item;
145 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
146 passwordLength, &password, &item);
147 if( err == GenericError ) {
148 err = SecKeychainFindInternetPassword(keychainOrArray,
149 16, "server", 16, "domain", 16, "account",
150 16, "path", 222, protocol, authenticationType,
151 passwordLength, &(password), 0);
154 if (err == noErr && password) {
155 SecKeychainItemFreeContent(0, password);
160 int apiMismatch(SecKeychainItemRef itemRef,
161 SecKeychainAttributeInfo *info,
162 SecItemClass *itemClass) {
164 SecKeychainAttributeList *attrList;
168 st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
169 &attrList, &length, &outData);
171 SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Deallocator doesn't match the allocator}}
175 int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef,
176 SecKeychainAttributeInfo *info,
177 SecItemClass *itemClass) {
178 unsigned int *ptr = 0;
183 SecKeychainAttributeList *attrList;
187 st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
188 &attrList, &length2, &outData2);
189 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
191 SecKeychainItemFreeContent(ptr, outData);
193 SecKeychainItemFreeAttributesAndData(attrList, outData2);
196 return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}}
199 int foo(CFTypeRef keychainOrArray, SecProtocolType protocol,
200 SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
201 unsigned int *ptr = 0;
207 st = SecKeychainFindInternetPassword(keychainOrArray,
208 16, "server", 16, "domain", 16, "account",
209 16, "path", 222, protocol, authenticationType,
210 &length, &(outData[3]), itemRef);
213 SecKeychainItemFreeContent(ptr, outData[3]);
215 if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
221 int testErrorCodeAsLHS(CFTypeRef keychainOrArray, SecProtocolType protocol,
222 SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
223 unsigned int *ptr = 0;
227 st = SecKeychainFindInternetPassword(keychainOrArray,
228 16, "server", 16, "domain", 16, "account",
229 16, "path", 222, protocol, authenticationType,
230 &length, &outData, itemRef);
232 SecKeychainItemFreeContent(ptr, outData);
237 void free(void *ptr);
238 void deallocateWithFree(void) {
239 unsigned int *ptr = 0;
243 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
245 free(outData); // expected-warning{{Deallocator doesn't match the allocator: 'SecKeychainItemFreeContent' should be used}}
248 // Typesdefs for CFStringCreateWithBytesNoCopy.
249 typedef char uint8_t;
250 typedef signed long CFIndex;
251 typedef UInt32 CFStringEncoding;
252 typedef unsigned Boolean;
253 typedef const struct __CFString * CFStringRef;
254 typedef const struct __CFAllocator * CFAllocatorRef;
255 extern const CFAllocatorRef kCFAllocatorDefault;
256 extern const CFAllocatorRef kCFAllocatorSystemDefault;
257 extern const CFAllocatorRef kCFAllocatorMalloc;
258 extern const CFAllocatorRef kCFAllocatorMallocZone;
259 extern const CFAllocatorRef kCFAllocatorNull;
260 extern const CFAllocatorRef kCFAllocatorUseContext;
261 CFStringRef CFStringCreateWithBytesNoCopy(CFAllocatorRef alloc, const uint8_t *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean externalFormat, CFAllocatorRef contentsDeallocator);
263 void DellocWithCFStringCreate1(CFAllocatorRef alloc) {
264 unsigned int *ptr = 0;
269 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
271 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorDefault); // expected-warning{{Deallocator doesn't match the allocator:}}
276 void DellocWithCFStringCreate2(CFAllocatorRef alloc) {
277 unsigned int *ptr = 0;
282 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
284 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); // expected-warning{{Allocated data is not released}}
289 void DellocWithCFStringCreate3(CFAllocatorRef alloc) {
290 unsigned int *ptr = 0;
295 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
297 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorUseContext);
302 void DellocWithCFStringCreate4(CFAllocatorRef alloc) {
303 unsigned int *ptr = 0;
308 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
310 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, 0); // expected-warning{{Deallocator doesn't match the allocator:}}
315 static CFAllocatorRef gKeychainDeallocator = 0;
317 static CFAllocatorRef GetKeychainDeallocator(void) {
318 return gKeychainDeallocator;
321 CFStringRef DellocWithCFStringCreate5(CFAllocatorRef alloc) {
322 unsigned int *ptr = 0;
327 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
329 return CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, GetKeychainDeallocator()); // no-warning
334 void radar10508828(void) {
337 OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
340 SecKeychainItemFreeContent(0, pwdBytes);
343 void radar10508828_20092614(void) {
346 OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
347 SecKeychainItemFreeContent(0, pwdBytes);
350 //Example from bug 10797.
352 const char *__WBASLLevelString(int level) {
356 static int *bug10798(int *p, int columns, int prevRow) {
358 row = p + prevRow * columns;
363 } while(10 >= row[1]);
367 // Test inter-procedural behaviour.
369 void my_FreeParam(void *attrList, void* X) {
370 SecKeychainItemFreeContent(attrList, X);
373 void *my_AllocateReturn(OSStatus *st) {
374 unsigned int *ptr = 0;
377 *st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
381 OSStatus my_Allocate_Param(void** password, UInt32* passwordLength) {
383 SecKeychainItemRef item;
384 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
385 passwordLength, password, &item);
389 void allocAndFree1(void) {
390 unsigned int *ptr = 0;
394 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
396 my_FreeParam(ptr, outData);
399 void consumeChar(char);
401 void allocNoFree2(int x) {
403 void *outData = my_AllocateReturn(&st);
405 consumeChar(*(char*)outData); // expected-warning{{Allocated data is not released:}}
408 consumeChar(*(char*)outData);
413 void allocAndFree2(void *attrList) {
415 void *outData = my_AllocateReturn(&st);
417 my_FreeParam(attrList, outData);
420 void allocNoFree3(void) {
424 OSStatus st = my_Allocate_Param(&outData, &length); // expected-warning{{Allocated data is not released}}
425 st = my_Allocate_Param(&outData2, &length); // expected-warning{{Allocated data is not released}}
428 void allocAndFree3(void *attrList) {
431 OSStatus st = my_Allocate_Param(&outData, &length);
433 SecKeychainItemFreeContent(attrList, outData);
436 typedef struct AuthorizationValue {
439 } AuthorizationValue;
440 typedef struct AuthorizationCallback {
441 OSStatus (*SetContextVal)(AuthorizationValue *inValue);
442 } AuthorizationCallback;
443 static AuthorizationCallback cb;
444 int radar_19196494(void) {
446 AuthorizationValue login_password = {};
447 UInt32 passwordLength;
448 void *passwordData = 0;
449 OSStatus err = SecKeychainFindGenericPassword(0, 0, "", 0, "", (UInt32 *)&login_password.length, (void**)&login_password.data, 0);
450 cb.SetContextVal(&login_password);
452 SecKeychainItemFreeContent(0, login_password.data);
457 int radar_19196494_v2(void) {
459 AuthorizationValue login_password = {};
460 OSStatus err = SecKeychainFindGenericPassword(0, 0, "", 0, "", (UInt32 *)&login_password.length, (void**)&login_password.data, 0);
461 if (!login_password.data) return 0;
462 cb.SetContextVal(&login_password);
464 SecKeychainItemFreeContent(0, login_password.data);