blob: 1725ce15f0e66dbf47ecdfa8140ce1e391fcb4ce [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=osx.SecKeychainAPI -fblocks %s -verify
Anna Zaks14b1af52017-01-13 00:50:41 +00002
3#include "Inputs/system-header-simulator-objc.h"
Anna Zaks15f496c2011-08-01 22:40:01 +00004
5// Fake typedefs.
6typedef unsigned int OSStatus;
7typedef unsigned int SecKeychainAttributeList;
8typedef unsigned int SecKeychainItemRef;
9typedef unsigned int SecItemClass;
10typedef unsigned int UInt32;
Anna Zaks15f496c2011-08-01 22:40:01 +000011typedef unsigned int SecProtocolType;
12typedef unsigned int SecAuthenticationType;
Anna Zaks680be292011-08-04 22:40:38 +000013typedef unsigned int SecKeychainAttributeInfo;
Anna Zaks15f496c2011-08-01 22:40:01 +000014enum {
15 noErr = 0,
16 GenericError = 1
17};
18
19// Functions that allocate data.
20OSStatus SecKeychainItemCopyContent (
21 SecKeychainItemRef itemRef,
22 SecItemClass *itemClass,
23 SecKeychainAttributeList *attrList,
24 UInt32 *length,
25 void **outData
26);
27OSStatus SecKeychainFindGenericPassword (
28 CFTypeRef keychainOrArray,
29 UInt32 serviceNameLength,
30 const char *serviceName,
31 UInt32 accountNameLength,
32 const char *accountName,
33 UInt32 *passwordLength,
34 void **passwordData,
35 SecKeychainItemRef *itemRef
36);
37OSStatus 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,
45 UInt32 pathLength,
46 const char *path,
47 UInt16 port,
48 SecProtocolType protocol,
49 SecAuthenticationType authenticationType,
50 UInt32 *passwordLength,
51 void **passwordData,
52 SecKeychainItemRef *itemRef
53);
Anna Zaks680be292011-08-04 22:40:38 +000054OSStatus SecKeychainItemCopyAttributesAndData (
55 SecKeychainItemRef itemRef,
56 SecKeychainAttributeInfo *info,
57 SecItemClass *itemClass,
58 SecKeychainAttributeList **attrList,
59 UInt32 *length,
60 void **outData
61);
Anna Zaks15f496c2011-08-01 22:40:01 +000062
Anna Zaks680be292011-08-04 22:40:38 +000063// Functions which free data.
Anna Zaks15f496c2011-08-01 22:40:01 +000064OSStatus SecKeychainItemFreeContent (
65 SecKeychainAttributeList *attrList,
66 void *data
67);
Anna Zaks680be292011-08-04 22:40:38 +000068OSStatus SecKeychainItemFreeAttributesAndData (
69 SecKeychainAttributeList *attrList,
70 void *data
71);
Anna Zaks15f496c2011-08-01 22:40:01 +000072
Anna Zaks388c18e2011-08-04 00:26:57 +000073void errRetVal() {
Anna Zaksfdd0aca2011-08-12 21:56:43 +000074 unsigned int *ptr = 0;
75 OSStatus st = 0;
76 UInt32 length;
77 void *outData;
78 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
Jordan Rosee37ab502012-11-15 19:11:43 +000079 if (st == GenericError)
Anna Zaks14b1af52017-01-13 00:50:41 +000080 SecKeychainItemFreeContent(ptr, outData);
Jordan Rosee37ab502012-11-15 19:11:43 +000081} // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
Anna Zaks388c18e2011-08-04 00:26:57 +000082
83// If null is passed in, the data is not allocated, so no need for the matching free.
84void fooDoNotReportNull() {
85 unsigned int *ptr = 0;
86 OSStatus st = 0;
87 UInt32 *length = 0;
88 void **outData = 0;
89 SecKeychainItemCopyContent(2, ptr, ptr, 0, 0);
90 SecKeychainItemCopyContent(2, ptr, ptr, length, outData);
91}// no-warning
92
Anna Zaks680be292011-08-04 22:40:38 +000093void doubleAlloc() {
94 unsigned int *ptr = 0;
95 OSStatus st = 0;
Anna Zaksc52bed12011-08-05 00:37:00 +000096 UInt32 length;
97 void *outData;
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:}}
100 if (st == noErr)
101 SecKeychainItemFreeContent(ptr, outData);
102}
Anna Zaks680be292011-08-04 22:40:38 +0000103
Anna Zaks388c18e2011-08-04 00:26:57 +0000104// Do not warn if undefined value is passed to a function.
105void fooOnlyFreeUndef() {
106 unsigned int *ptr = 0;
107 OSStatus st = 0;
108 UInt32 length;
109 void *outData;
110 SecKeychainItemFreeContent(ptr, outData);
111}// no-warning
112
113// Do not warn if the address is a parameter in the enclosing function.
Anna Zaks680be292011-08-04 22:40:38 +0000114void fooOnlyFreeParam(void *attrList, void* X) {
115 SecKeychainItemFreeContent(attrList, X);
Anna Zaks388c18e2011-08-04 00:26:57 +0000116}// no-warning
117
Anna Zaksfdd0aca2011-08-12 21:56:43 +0000118// If we are returning the value, do not report.
Anna Zaks388c18e2011-08-04 00:26:57 +0000119void* returnContent() {
120 unsigned int *ptr = 0;
121 OSStatus st = 0;
122 UInt32 length;
123 void *outData;
124 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
125 return outData;
126} // no-warning
127
Anna Zaks19a66672012-02-21 00:00:44 +0000128// Password was passed in as an argument and does not have to be deleted.
Anna Zaks59d741f2011-08-12 22:47:22 +0000129OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) {
Anna Zaks80319c12011-08-13 02:10:15 +0000130 OSStatus err;
131 SecKeychainItemRef item;
132 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
133 passwordLength, password, &item);
134 return err;
Anna Zaks59d741f2011-08-12 22:47:22 +0000135} // no-warning
136
Anna Zaks80319c12011-08-13 02:10:15 +0000137// Make sure we do not report an error if we call free only if password != 0.
Anna Zaks01ae1e12011-08-16 16:30:24 +0000138// Also, do not report double allocation if first allocation returned an error.
139OSStatus testSecKeychainFindGenericPassword(UInt32* passwordLength,
140 CFTypeRef keychainOrArray, SecProtocolType protocol,
141 SecAuthenticationType authenticationType) {
Anna Zaks80319c12011-08-13 02:10:15 +0000142 OSStatus err;
143 SecKeychainItemRef item;
144 void *password;
145 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
146 passwordLength, &password, &item);
Anna Zaks01ae1e12011-08-16 16:30:24 +0000147 if( err == GenericError ) {
148 err = SecKeychainFindInternetPassword(keychainOrArray,
149 16, "server", 16, "domain", 16, "account",
150 16, "path", 222, protocol, authenticationType,
151 passwordLength, &(password), 0);
152 }
153
Anna Zaks80319c12011-08-13 02:10:15 +0000154 if (err == noErr && password) {
155 SecKeychainItemFreeContent(0, password);
156 }
157 return err;
158}
159
Anna Zaks680be292011-08-04 22:40:38 +0000160int apiMismatch(SecKeychainItemRef itemRef,
161 SecKeychainAttributeInfo *info,
162 SecItemClass *itemClass) {
163 OSStatus st = 0;
164 SecKeychainAttributeList *attrList;
165 UInt32 length;
166 void *outData;
167
168 st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
169 &attrList, &length, &outData);
170 if (st == noErr)
Anna Zaksbd7972b2011-08-22 23:18:12 +0000171 SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Deallocator doesn't match the allocator}}
Anna Zaks680be292011-08-04 22:40:38 +0000172 return 0;
173}
174
175int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef,
176 SecKeychainAttributeInfo *info,
177 SecItemClass *itemClass) {
178 unsigned int *ptr = 0;
179 OSStatus st = 0;
180 UInt32 length;
181 void *outData;
182 OSStatus st2 = 0;
183 SecKeychainAttributeList *attrList;
184 UInt32 length2;
185 void *outData2;
186
187 st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
188 &attrList, &length2, &outData2);
189 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
190 if (st == noErr) {
191 SecKeychainItemFreeContent(ptr, outData);
192 if (st2 == noErr) {
193 SecKeychainItemFreeAttributesAndData(attrList, outData2);
194 }
195 }
196 return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}}
197}
198
Anna Zaks80319c12011-08-13 02:10:15 +0000199int foo(CFTypeRef keychainOrArray, SecProtocolType protocol,
200 SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
Anna Zaks15f496c2011-08-01 22:40:01 +0000201 unsigned int *ptr = 0;
202 OSStatus st = 0;
203
204 UInt32 length;
Anna Zaksfdd0aca2011-08-12 21:56:43 +0000205 void *outData[5];
Anna Zaks15f496c2011-08-01 22:40:01 +0000206
Anna Zaks80319c12011-08-13 02:10:15 +0000207 st = SecKeychainFindInternetPassword(keychainOrArray,
208 16, "server", 16, "domain", 16, "account",
209 16, "path", 222, protocol, authenticationType,
210 &length, &(outData[3]), itemRef);
Anna Zaksfdd0aca2011-08-12 21:56:43 +0000211 if (length == 5) {
212 if (st == noErr)
213 SecKeychainItemFreeContent(ptr, outData[3]);
214 }
Anna Zaks14b1af52017-01-13 00:50:41 +0000215 if (length) { // TODO: We do not report a warning here since the symbol is no longer live, but it's not marked as dead.
Anna Zaksfdd0aca2011-08-12 21:56:43 +0000216 length++;
217 }
Anna Zaks15f496c2011-08-01 22:40:01 +0000218 return 0;
Anna Zaks14b1af52017-01-13 00:50:41 +0000219}
220
221int testErrorCodeAsLHS(CFTypeRef keychainOrArray, SecProtocolType protocol,
222 SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
223 unsigned int *ptr = 0;
224 OSStatus st = 0;
225 UInt32 length;
226 void *outData;
227 st = SecKeychainFindInternetPassword(keychainOrArray,
228 16, "server", 16, "domain", 16, "account",
229 16, "path", 222, protocol, authenticationType,
230 &length, &outData, itemRef);
231 if (noErr == st)
232 SecKeychainItemFreeContent(ptr, outData);
233
234 return 0;
235}
Anna Zaksbd7972b2011-08-22 23:18:12 +0000236
237void free(void *ptr);
238void deallocateWithFree() {
239 unsigned int *ptr = 0;
240 OSStatus st = 0;
241 UInt32 length;
242 void *outData;
243 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
244 if (st == noErr)
245 free(outData); // expected-warning{{Deallocator doesn't match the allocator: 'SecKeychainItemFreeContent' should be used}}
246}
247
Anna Zaks0897a232011-08-24 00:06:27 +0000248// Typesdefs for CFStringCreateWithBytesNoCopy.
249typedef char uint8_t;
250typedef signed long CFIndex;
251typedef UInt32 CFStringEncoding;
252typedef unsigned Boolean;
253typedef const struct __CFString * CFStringRef;
254typedef const struct __CFAllocator * CFAllocatorRef;
255extern const CFAllocatorRef kCFAllocatorDefault;
256extern const CFAllocatorRef kCFAllocatorSystemDefault;
257extern const CFAllocatorRef kCFAllocatorMalloc;
258extern const CFAllocatorRef kCFAllocatorMallocZone;
259extern const CFAllocatorRef kCFAllocatorNull;
260extern const CFAllocatorRef kCFAllocatorUseContext;
261CFStringRef CFStringCreateWithBytesNoCopy(CFAllocatorRef alloc, const uint8_t *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean externalFormat, CFAllocatorRef contentsDeallocator);
Anna Zaks0897a232011-08-24 00:06:27 +0000262
263void DellocWithCFStringCreate1(CFAllocatorRef alloc) {
264 unsigned int *ptr = 0;
265 OSStatus st = 0;
266 UInt32 length;
267 void *bytes;
268 char * x;
269 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
270 if (st == noErr) {
271 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorDefault); // expected-warning{{Deallocator doesn't match the allocator:}}
272 CFRelease(userStr);
273 }
274}
275
276void DellocWithCFStringCreate2(CFAllocatorRef alloc) {
277 unsigned int *ptr = 0;
278 OSStatus st = 0;
279 UInt32 length;
280 void *bytes;
281 char * x;
282 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
283 if (st == noErr) {
Anna Zaks06a77fc2012-02-28 01:54:22 +0000284 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); // expected-warning{{Allocated data is not released}}
285 CFRelease(userStr);
Anna Zaks0897a232011-08-24 00:06:27 +0000286 }
287}
288
289void DellocWithCFStringCreate3(CFAllocatorRef alloc) {
290 unsigned int *ptr = 0;
291 OSStatus st = 0;
292 UInt32 length;
293 void *bytes;
294 char * x;
295 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
296 if (st == noErr) {
297 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorUseContext);
298 CFRelease(userStr);
299 }
300}
301
302void DellocWithCFStringCreate4(CFAllocatorRef alloc) {
303 unsigned int *ptr = 0;
304 OSStatus st = 0;
305 UInt32 length;
306 void *bytes;
307 char * x;
308 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
309 if (st == noErr) {
310 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, 0); // expected-warning{{Deallocator doesn't match the allocator:}}
311 CFRelease(userStr);
312 }
313}
Anna Zakscda129e2011-08-29 20:05:54 +0000314
Anna Zaks030e65d2013-01-07 19:13:00 +0000315static CFAllocatorRef gKeychainDeallocator = 0;
316
317static CFAllocatorRef GetKeychainDeallocator() {
318 return gKeychainDeallocator;
319}
320
321CFStringRef DellocWithCFStringCreate5(CFAllocatorRef alloc) {
322 unsigned int *ptr = 0;
323 OSStatus st = 0;
324 UInt32 length;
325 void *bytes;
326 char * x;
327 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
328 if (st == noErr) {
329 return CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, GetKeychainDeallocator()); // no-warning
330 }
331 return 0;
332}
333
Anna Zaks719051e2011-12-01 16:41:58 +0000334void radar10508828() {
335 UInt32 pwdLen = 0;
336 void* pwdBytes = 0;
337 OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
338#pragma unused(rc)
339 if (pwdBytes)
340 SecKeychainItemFreeContent(0, pwdBytes);
341}
342
Anna Zaks14b1af52017-01-13 00:50:41 +0000343void radar10508828_20092614() {
Anna Zaks719051e2011-12-01 16:41:58 +0000344 UInt32 pwdLen = 0;
345 void* pwdBytes = 0;
346 OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
Anna Zaks14b1af52017-01-13 00:50:41 +0000347 SecKeychainItemFreeContent(0, pwdBytes);
Anna Zaks719051e2011-12-01 16:41:58 +0000348}
349
Anna Zakscda129e2011-08-29 20:05:54 +0000350//Example from bug 10797.
351__inline__ static
352const char *__WBASLLevelString(int level) {
353 return "foo";
354}
Anna Zaks814adf72011-08-29 20:43:37 +0000355
356static int *bug10798(int *p, int columns, int prevRow) {
357 int *row = 0;
358 row = p + prevRow * columns;
359 prevRow += 2;
360 do {
361 ++prevRow;
362 row+=columns;
363 } while(10 >= row[1]);
364 return row;
365}
Anna Zaks19a66672012-02-21 00:00:44 +0000366
367// Test inter-procedural behaviour.
368
369void my_FreeParam(void *attrList, void* X) {
370 SecKeychainItemFreeContent(attrList, X);
371}
372
373void *my_AllocateReturn(OSStatus *st) {
374 unsigned int *ptr = 0;
375 UInt32 length;
376 void *outData;
377 *st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
378 return outData;
379}
380
381OSStatus my_Allocate_Param(void** password, UInt32* passwordLength) {
382 OSStatus err;
383 SecKeychainItemRef item;
384 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
385 passwordLength, password, &item);
386 return err;
387}
388
389void allocAndFree1() {
390 unsigned int *ptr = 0;
391 OSStatus st = 0;
392 UInt32 length;
393 void *outData;
394 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
395 if (st == noErr)
396 my_FreeParam(ptr, outData);
397}
398
Anna Zaks4b062cb2012-02-23 22:53:29 +0000399void consumeChar(char);
400
401void allocNoFree2(int x) {
Anna Zaks19a66672012-02-21 00:00:44 +0000402 OSStatus st = 0;
Anna Zaks4b062cb2012-02-23 22:53:29 +0000403 void *outData = my_AllocateReturn(&st);
404 if (x) {
405 consumeChar(*(char*)outData); // expected-warning{{Allocated data is not released:}}
406 return;
407 } else {
408 consumeChar(*(char*)outData);
409 }
410 return;
Anna Zaks19a66672012-02-21 00:00:44 +0000411}
412
413void allocAndFree2(void *attrList) {
414 OSStatus st = 0;
415 void *outData = my_AllocateReturn(&st);
416 if (st == noErr)
417 my_FreeParam(attrList, outData);
418}
419
420void allocNoFree3() {
421 UInt32 length = 32;
Anna Zaks6ca4fd52012-02-28 03:07:06 +0000422 void *outData;
423 void *outData2;
Anna Zaks19a66672012-02-21 00:00:44 +0000424 OSStatus st = my_Allocate_Param(&outData, &length); // expected-warning{{Allocated data is not released}}
Anna Zaks6ca4fd52012-02-28 03:07:06 +0000425 st = my_Allocate_Param(&outData2, &length); // expected-warning{{Allocated data is not released}}
Anna Zaks19a66672012-02-21 00:00:44 +0000426}
427
428void allocAndFree3(void *attrList) {
429 UInt32 length = 32;
430 void *outData;
431 OSStatus st = my_Allocate_Param(&outData, &length);
432 if (st == noErr)
433 SecKeychainItemFreeContent(attrList, outData);
Anna Zaks19a66672012-02-21 00:00:44 +0000434}
435
Anna Zaks14b1af52017-01-13 00:50:41 +0000436typedef struct AuthorizationValue {
437 int length;
438 void *data;
439} AuthorizationValue;
440typedef struct AuthorizationCallback {
441 OSStatus (*SetContextVal)(AuthorizationValue *inValue);
442} AuthorizationCallback;
443static AuthorizationCallback cb;
444int radar_19196494() {
445 @autoreleasepool {
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);
451 if (err == noErr) {
452 SecKeychainItemFreeContent(0, login_password.data);
453 }
454 }
455 return 0;
456}