blob: 4fc48c066f9dff0f4ef4ecf365333a89f48c65b7 [file] [log] [blame]
Jordan Roseee049592012-08-21 21:44:07 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=osx.SecKeychainAPI %s -verify
Anna Zaksf57be282011-08-01 22:40:01 +00002
3// Fake typedefs.
4typedef unsigned int OSStatus;
5typedef unsigned int SecKeychainAttributeList;
6typedef unsigned int SecKeychainItemRef;
7typedef unsigned int SecItemClass;
8typedef unsigned int UInt32;
9typedef unsigned int CFTypeRef;
10typedef unsigned int UInt16;
11typedef unsigned int SecProtocolType;
12typedef unsigned int SecAuthenticationType;
Anna Zaks62a811d2011-08-04 22:40:38 +000013typedef unsigned int SecKeychainAttributeInfo;
Anna Zaksf57be282011-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 Zaks62a811d2011-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 Zaksf57be282011-08-01 22:40:01 +000062
Anna Zaks62a811d2011-08-04 22:40:38 +000063// Functions which free data.
Anna Zaksf57be282011-08-01 22:40:01 +000064OSStatus SecKeychainItemFreeContent (
65 SecKeychainAttributeList *attrList,
66 void *data
67);
Anna Zaks62a811d2011-08-04 22:40:38 +000068OSStatus SecKeychainItemFreeAttributesAndData (
69 SecKeychainAttributeList *attrList,
70 void *data
71);
Anna Zaksf57be282011-08-01 22:40:01 +000072
Anna Zaks03826aa2011-08-04 00:26:57 +000073void errRetVal() {
Anna Zaks703ffb12011-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 Rose63bc1862012-11-15 19:11:43 +000079 if (st == GenericError)
Anna Zaksee5a21f2011-12-01 16:41:58 +000080 SecKeychainItemFreeContent(ptr, outData); // expected-warning{{Only call free if a valid (non-NULL) buffer was returned}}
Jordan Rose63bc1862012-11-15 19:11:43 +000081} // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
Anna Zaks03826aa2011-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 Zaks62a811d2011-08-04 22:40:38 +000093void doubleAlloc() {
94 unsigned int *ptr = 0;
95 OSStatus st = 0;
Anna Zaksca0b57e2011-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 Zaks62a811d2011-08-04 22:40:38 +0000103
Anna Zaks03826aa2011-08-04 00:26:57 +0000104void fooOnlyFree() {
105 unsigned int *ptr = 0;
106 OSStatus st = 0;
107 UInt32 length;
108 void *outData = &length;
109 SecKeychainItemFreeContent(ptr, outData);// expected-warning{{Trying to free data which has not been allocated}}
110}
111
112// Do not warn if undefined value is passed to a function.
113void fooOnlyFreeUndef() {
114 unsigned int *ptr = 0;
115 OSStatus st = 0;
116 UInt32 length;
117 void *outData;
118 SecKeychainItemFreeContent(ptr, outData);
119}// no-warning
120
121// Do not warn if the address is a parameter in the enclosing function.
Anna Zaks62a811d2011-08-04 22:40:38 +0000122void fooOnlyFreeParam(void *attrList, void* X) {
123 SecKeychainItemFreeContent(attrList, X);
Anna Zaks03826aa2011-08-04 00:26:57 +0000124}// no-warning
125
Anna Zaks703ffb12011-08-12 21:56:43 +0000126// If we are returning the value, do not report.
Anna Zaks03826aa2011-08-04 00:26:57 +0000127void* returnContent() {
128 unsigned int *ptr = 0;
129 OSStatus st = 0;
130 UInt32 length;
131 void *outData;
132 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
133 return outData;
134} // no-warning
135
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000136// Password was passed in as an argument and does not have to be deleted.
Anna Zaks79c9c752011-08-12 22:47:22 +0000137OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) {
Anna Zaksf7ce52b2011-08-13 02:10:15 +0000138 OSStatus err;
139 SecKeychainItemRef item;
140 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
141 passwordLength, password, &item);
142 return err;
Anna Zaks79c9c752011-08-12 22:47:22 +0000143} // no-warning
144
Anna Zaksf7ce52b2011-08-13 02:10:15 +0000145// Make sure we do not report an error if we call free only if password != 0.
Anna Zaksf0c7fe52011-08-16 16:30:24 +0000146// Also, do not report double allocation if first allocation returned an error.
147OSStatus testSecKeychainFindGenericPassword(UInt32* passwordLength,
148 CFTypeRef keychainOrArray, SecProtocolType protocol,
149 SecAuthenticationType authenticationType) {
Anna Zaksf7ce52b2011-08-13 02:10:15 +0000150 OSStatus err;
151 SecKeychainItemRef item;
152 void *password;
153 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
154 passwordLength, &password, &item);
Anna Zaksf0c7fe52011-08-16 16:30:24 +0000155 if( err == GenericError ) {
156 err = SecKeychainFindInternetPassword(keychainOrArray,
157 16, "server", 16, "domain", 16, "account",
158 16, "path", 222, protocol, authenticationType,
159 passwordLength, &(password), 0);
160 }
161
Anna Zaksf7ce52b2011-08-13 02:10:15 +0000162 if (err == noErr && password) {
163 SecKeychainItemFreeContent(0, password);
164 }
165 return err;
166}
167
Anna Zaks62a811d2011-08-04 22:40:38 +0000168int apiMismatch(SecKeychainItemRef itemRef,
169 SecKeychainAttributeInfo *info,
170 SecItemClass *itemClass) {
171 OSStatus st = 0;
172 SecKeychainAttributeList *attrList;
173 UInt32 length;
174 void *outData;
175
176 st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
177 &attrList, &length, &outData);
178 if (st == noErr)
Anna Zaks7bbd1662011-08-22 23:18:12 +0000179 SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Deallocator doesn't match the allocator}}
Anna Zaks62a811d2011-08-04 22:40:38 +0000180 return 0;
181}
182
183int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef,
184 SecKeychainAttributeInfo *info,
185 SecItemClass *itemClass) {
186 unsigned int *ptr = 0;
187 OSStatus st = 0;
188 UInt32 length;
189 void *outData;
190 OSStatus st2 = 0;
191 SecKeychainAttributeList *attrList;
192 UInt32 length2;
193 void *outData2;
194
195 st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
196 &attrList, &length2, &outData2);
197 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
198 if (st == noErr) {
199 SecKeychainItemFreeContent(ptr, outData);
200 if (st2 == noErr) {
201 SecKeychainItemFreeAttributesAndData(attrList, outData2);
202 }
203 }
204 return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}}
205}
206
Anna Zaksf7ce52b2011-08-13 02:10:15 +0000207int foo(CFTypeRef keychainOrArray, SecProtocolType protocol,
208 SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
Anna Zaksf57be282011-08-01 22:40:01 +0000209 unsigned int *ptr = 0;
210 OSStatus st = 0;
211
212 UInt32 length;
Anna Zaks703ffb12011-08-12 21:56:43 +0000213 void *outData[5];
Anna Zaksf57be282011-08-01 22:40:01 +0000214
Anna Zaksf7ce52b2011-08-13 02:10:15 +0000215 st = SecKeychainFindInternetPassword(keychainOrArray,
216 16, "server", 16, "domain", 16, "account",
217 16, "path", 222, protocol, authenticationType,
218 &length, &(outData[3]), itemRef);
Anna Zaks703ffb12011-08-12 21:56:43 +0000219 if (length == 5) {
220 if (st == noErr)
221 SecKeychainItemFreeContent(ptr, outData[3]);
222 }
Ted Kremenekc4bac8e2012-08-16 17:45:23 +0000223 if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
Anna Zaks703ffb12011-08-12 21:56:43 +0000224 length++;
225 }
Anna Zaksf57be282011-08-01 22:40:01 +0000226 return 0;
Anna Zaks03826aa2011-08-04 00:26:57 +0000227}// no-warning
Anna Zaks7bbd1662011-08-22 23:18:12 +0000228
229void free(void *ptr);
230void deallocateWithFree() {
231 unsigned int *ptr = 0;
232 OSStatus st = 0;
233 UInt32 length;
234 void *outData;
235 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
236 if (st == noErr)
237 free(outData); // expected-warning{{Deallocator doesn't match the allocator: 'SecKeychainItemFreeContent' should be used}}
238}
239
Anna Zaks6cf0ed02011-08-24 00:06:27 +0000240// Typesdefs for CFStringCreateWithBytesNoCopy.
241typedef char uint8_t;
242typedef signed long CFIndex;
243typedef UInt32 CFStringEncoding;
244typedef unsigned Boolean;
245typedef const struct __CFString * CFStringRef;
246typedef const struct __CFAllocator * CFAllocatorRef;
247extern const CFAllocatorRef kCFAllocatorDefault;
248extern const CFAllocatorRef kCFAllocatorSystemDefault;
249extern const CFAllocatorRef kCFAllocatorMalloc;
250extern const CFAllocatorRef kCFAllocatorMallocZone;
251extern const CFAllocatorRef kCFAllocatorNull;
252extern const CFAllocatorRef kCFAllocatorUseContext;
253CFStringRef CFStringCreateWithBytesNoCopy(CFAllocatorRef alloc, const uint8_t *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean externalFormat, CFAllocatorRef contentsDeallocator);
254extern void CFRelease(CFStringRef cf);
255
256void DellocWithCFStringCreate1(CFAllocatorRef alloc) {
257 unsigned int *ptr = 0;
258 OSStatus st = 0;
259 UInt32 length;
260 void *bytes;
261 char * x;
262 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
263 if (st == noErr) {
264 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorDefault); // expected-warning{{Deallocator doesn't match the allocator:}}
265 CFRelease(userStr);
266 }
267}
268
269void DellocWithCFStringCreate2(CFAllocatorRef alloc) {
270 unsigned int *ptr = 0;
271 OSStatus st = 0;
272 UInt32 length;
273 void *bytes;
274 char * x;
275 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
276 if (st == noErr) {
Anna Zaks07d39a42012-02-28 01:54:22 +0000277 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); // expected-warning{{Allocated data is not released}}
278 CFRelease(userStr);
Anna Zaks6cf0ed02011-08-24 00:06:27 +0000279 }
280}
281
282void DellocWithCFStringCreate3(CFAllocatorRef alloc) {
283 unsigned int *ptr = 0;
284 OSStatus st = 0;
285 UInt32 length;
286 void *bytes;
287 char * x;
288 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
289 if (st == noErr) {
290 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorUseContext);
291 CFRelease(userStr);
292 }
293}
294
295void DellocWithCFStringCreate4(CFAllocatorRef alloc) {
296 unsigned int *ptr = 0;
297 OSStatus st = 0;
298 UInt32 length;
299 void *bytes;
300 char * x;
301 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
302 if (st == noErr) {
303 CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, 0); // expected-warning{{Deallocator doesn't match the allocator:}}
304 CFRelease(userStr);
305 }
306}
Anna Zaks5c96f862011-08-29 20:05:54 +0000307
Anna Zaks0b67c752013-01-07 19:13:00 +0000308static CFAllocatorRef gKeychainDeallocator = 0;
309
310static CFAllocatorRef GetKeychainDeallocator() {
311 return gKeychainDeallocator;
312}
313
314CFStringRef DellocWithCFStringCreate5(CFAllocatorRef alloc) {
315 unsigned int *ptr = 0;
316 OSStatus st = 0;
317 UInt32 length;
318 void *bytes;
319 char * x;
320 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
321 if (st == noErr) {
322 return CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, GetKeychainDeallocator()); // no-warning
323 }
324 return 0;
325}
326
Anna Zaksee5a21f2011-12-01 16:41:58 +0000327void radar10508828() {
328 UInt32 pwdLen = 0;
329 void* pwdBytes = 0;
330 OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
331#pragma unused(rc)
332 if (pwdBytes)
333 SecKeychainItemFreeContent(0, pwdBytes);
334}
335
336void radar10508828_2() {
337 UInt32 pwdLen = 0;
338 void* pwdBytes = 0;
339 OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
Ted Kremenekc4bac8e2012-08-16 17:45:23 +0000340 SecKeychainItemFreeContent(0, pwdBytes); // expected-warning {{Only call free if a valid (non-NULL) buffer was returned}}
Anna Zaksee5a21f2011-12-01 16:41:58 +0000341}
342
Anna Zaks5c96f862011-08-29 20:05:54 +0000343//Example from bug 10797.
344__inline__ static
345const char *__WBASLLevelString(int level) {
346 return "foo";
347}
Anna Zaks8b6eb7c2011-08-29 20:43:37 +0000348
349static int *bug10798(int *p, int columns, int prevRow) {
350 int *row = 0;
351 row = p + prevRow * columns;
352 prevRow += 2;
353 do {
354 ++prevRow;
355 row+=columns;
356 } while(10 >= row[1]);
357 return row;
358}
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000359
360// Test inter-procedural behaviour.
361
362void my_FreeParam(void *attrList, void* X) {
363 SecKeychainItemFreeContent(attrList, X);
364}
365
366void *my_AllocateReturn(OSStatus *st) {
367 unsigned int *ptr = 0;
368 UInt32 length;
369 void *outData;
370 *st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
371 return outData;
372}
373
374OSStatus my_Allocate_Param(void** password, UInt32* passwordLength) {
375 OSStatus err;
376 SecKeychainItemRef item;
377 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
378 passwordLength, password, &item);
379 return err;
380}
381
382void allocAndFree1() {
383 unsigned int *ptr = 0;
384 OSStatus st = 0;
385 UInt32 length;
386 void *outData;
387 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
388 if (st == noErr)
389 my_FreeParam(ptr, outData);
390}
391
Anna Zaksd708bac2012-02-23 22:53:29 +0000392void consumeChar(char);
393
394void allocNoFree2(int x) {
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000395 OSStatus st = 0;
Anna Zaksd708bac2012-02-23 22:53:29 +0000396 void *outData = my_AllocateReturn(&st);
397 if (x) {
398 consumeChar(*(char*)outData); // expected-warning{{Allocated data is not released:}}
399 return;
400 } else {
401 consumeChar(*(char*)outData);
402 }
403 return;
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000404}
405
406void allocAndFree2(void *attrList) {
407 OSStatus st = 0;
408 void *outData = my_AllocateReturn(&st);
409 if (st == noErr)
410 my_FreeParam(attrList, outData);
411}
412
413void allocNoFree3() {
414 UInt32 length = 32;
Anna Zaks721aa372012-02-28 03:07:06 +0000415 void *outData;
416 void *outData2;
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000417 OSStatus st = my_Allocate_Param(&outData, &length); // expected-warning{{Allocated data is not released}}
Anna Zaks721aa372012-02-28 03:07:06 +0000418 st = my_Allocate_Param(&outData2, &length); // expected-warning{{Allocated data is not released}}
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000419}
420
421void allocAndFree3(void *attrList) {
422 UInt32 length = 32;
423 void *outData;
424 OSStatus st = my_Allocate_Param(&outData, &length);
425 if (st == noErr)
426 SecKeychainItemFreeContent(attrList, outData);
Anna Zaks9c1e1bd2012-02-21 00:00:44 +0000427}
428