]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/keychainAPI.m
Vendor import of clang trunk r300422:
[FreeBSD/FreeBSD.git] / test / Analysis / keychainAPI.m
1 // RUN: %clang_analyze_cc1 -analyzer-checker=osx.SecKeychainAPI -fblocks %s -verify
2
3 #include "Inputs/system-header-simulator-objc.h"
4
5 // Fake typedefs.
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;
14 enum {
15   noErr                      = 0,
16   GenericError               = 1
17 };
18
19 // Functions that allocate data.
20 OSStatus SecKeychainItemCopyContent (
21     SecKeychainItemRef itemRef,
22     SecItemClass *itemClass,
23     SecKeychainAttributeList *attrList,
24     UInt32 *length,
25     void **outData
26 );
27 OSStatus 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 );
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,
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 );
54 OSStatus SecKeychainItemCopyAttributesAndData (
55    SecKeychainItemRef itemRef,
56    SecKeychainAttributeInfo *info,
57    SecItemClass *itemClass,
58    SecKeychainAttributeList **attrList,
59    UInt32 *length,
60    void **outData
61 );
62
63 // Functions which free data.
64 OSStatus SecKeychainItemFreeContent (
65     SecKeychainAttributeList *attrList,
66     void *data
67 );
68 OSStatus SecKeychainItemFreeAttributesAndData (
69    SecKeychainAttributeList *attrList,
70    void *data
71 );
72
73 void errRetVal() {
74   unsigned int *ptr = 0;
75   OSStatus st = 0;
76   UInt32 length;
77   void *outData;
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'}}
82
83 // If null is passed in, the data is not allocated, so no need for the matching free.
84 void 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
93 void doubleAlloc() {
94     unsigned int *ptr = 0;
95     OSStatus st = 0;
96     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 }
103
104 // Do not warn if undefined value is passed to a function.
105 void 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.
114 void fooOnlyFreeParam(void *attrList, void* X) {
115     SecKeychainItemFreeContent(attrList, X); 
116 }// no-warning
117
118 // If we are returning the value, do not report.
119 void* 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
128 // Password was passed in as an argument and does not have to be deleted.
129 OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) {
130   OSStatus err;
131   SecKeychainItemRef item;
132   err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
133                                        passwordLength, password, &item);
134   return err;
135 } // no-warning
136
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) {
142   OSStatus err;
143   SecKeychainItemRef item;
144   void *password;
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);
152   }
153
154   if (err == noErr && password) {
155     SecKeychainItemFreeContent(0, password);
156   }
157   return err;
158 }
159
160 int 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)
171     SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Deallocator doesn't match the allocator}}
172   return 0;
173 }
174
175 int 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
199 int foo(CFTypeRef keychainOrArray, SecProtocolType protocol, 
200         SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
201   unsigned int *ptr = 0;
202   OSStatus st = 0;
203
204   UInt32 length;
205   void *outData[5];
206
207   st = SecKeychainFindInternetPassword(keychainOrArray, 
208                                        16, "server", 16, "domain", 16, "account",
209                                        16, "path", 222, protocol, authenticationType,
210                                        &length, &(outData[3]), itemRef);
211   if (length == 5) {
212     if (st == noErr)
213       SecKeychainItemFreeContent(ptr, outData[3]);
214   }
215   if (length) { // TODO: We do not report a warning here since the symbol is no longer live, but it's not marked as dead.
216     length++;
217   }
218   return 0;
219 }
220
221 int 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 }
236
237 void free(void *ptr);
238 void 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
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);
262
263 void 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
276 void 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) {
284     CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); // expected-warning{{Allocated data is not released}}
285     CFRelease(userStr); 
286   }
287 }
288
289 void 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
302 void 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 }
314
315 static CFAllocatorRef gKeychainDeallocator = 0;
316
317 static CFAllocatorRef GetKeychainDeallocator() {  
318   return gKeychainDeallocator;
319 }
320
321 CFStringRef 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
334 void 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
343 void radar10508828_20092614() {
344   UInt32 pwdLen = 0;
345   void*  pwdBytes = 0;
346   OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
347   SecKeychainItemFreeContent(0, pwdBytes);
348 }
349
350 //Example from bug 10797.
351 __inline__ static
352 const char *__WBASLLevelString(int level) {
353   return "foo";
354 }
355
356 static 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 }
366
367 // Test inter-procedural behaviour.
368
369 void my_FreeParam(void *attrList, void* X) {
370     SecKeychainItemFreeContent(attrList, X); 
371 }
372
373 void *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
381 OSStatus 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
389 void 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
399 void consumeChar(char);
400
401 void allocNoFree2(int x) {
402     OSStatus st = 0;
403     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;
411 }
412
413 void allocAndFree2(void *attrList) {
414     OSStatus st = 0;
415     void *outData = my_AllocateReturn(&st);
416     if (st == noErr)
417       my_FreeParam(attrList, outData);
418 }
419
420 void allocNoFree3() {
421     UInt32 length = 32;
422     void *outData;    
423     void *outData2;
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}}
426 }
427
428 void 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);
434 }
435
436 typedef struct AuthorizationValue {
437     int length;
438     void *data;
439 } AuthorizationValue;
440 typedef struct AuthorizationCallback {
441     OSStatus (*SetContextVal)(AuthorizationValue *inValue);
442 } AuthorizationCallback;
443 static AuthorizationCallback cb;
444 int 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 }