keychainAPI.m revision 62a811d171fd16cb45b4617be40d10aec8578c07
1// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.osx.KeychainAPI %s -verify
2
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;
13typedef unsigned int SecKeychainAttributeInfo;
14enum {
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);
54OSStatus 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.
64OSStatus SecKeychainItemFreeContent (
65    SecKeychainAttributeList *attrList,
66    void *data
67);
68OSStatus SecKeychainItemFreeAttributesAndData (
69   SecKeychainAttributeList *attrList,
70   void *data
71);
72
73void 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) // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}}
80		SecKeychainItemFreeContent(ptr, outData); // expected-warning{{Trying to free data which has not been allocated.}}
81}
82
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
93void doubleAlloc() {
94    unsigned int *ptr = 0;
95    OSStatus st = 0;
96    UInt32 *length = 0;
97    void **outData = 0;
98    SecKeychainItemCopyContent(2, ptr, ptr, length, outData);
99    SecKeychainItemCopyContent(2, ptr, ptr, length, outData);
100}// no-warning
101
102void fooOnlyFree() {
103  unsigned int *ptr = 0;
104  OSStatus st = 0;
105  UInt32 length;
106  void *outData = &length;
107  SecKeychainItemFreeContent(ptr, outData);// expected-warning{{Trying to free data which has not been allocated}}
108}
109
110// Do not warn if undefined value is passed to a function.
111void fooOnlyFreeUndef() {
112  unsigned int *ptr = 0;
113  OSStatus st = 0;
114  UInt32 length;
115  void *outData;
116  SecKeychainItemFreeContent(ptr, outData);
117}// no-warning
118
119// Do not warn if the address is a parameter in the enclosing function.
120void fooOnlyFreeParam(void *attrList, void* X) {
121    SecKeychainItemFreeContent(attrList, X); 
122}// no-warning
123
124// If we are returning the value, no not report.
125void* returnContent() {
126  unsigned int *ptr = 0;
127  OSStatus st = 0;
128  UInt32 length;
129  void *outData;
130  st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
131  return outData;
132} // no-warning
133
134int apiMismatch(SecKeychainItemRef itemRef, 
135         SecKeychainAttributeInfo *info,
136         SecItemClass *itemClass) {
137  OSStatus st = 0;
138  SecKeychainAttributeList *attrList;
139  UInt32 length;
140  void *outData;
141  
142  st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, 
143                                            &attrList, &length, &outData); 
144  if (st == noErr)
145    SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Allocator doesn't match the deallocator}}
146  return 0;
147}
148
149int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef, 
150                                              SecKeychainAttributeInfo *info,
151                                              SecItemClass *itemClass) {
152  unsigned int *ptr = 0;
153  OSStatus st = 0;
154  UInt32 length;
155  void *outData;
156  OSStatus st2 = 0;
157  SecKeychainAttributeList *attrList;
158  UInt32 length2;
159  void *outData2;
160
161  st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, 
162                                             &attrList, &length2, &outData2);
163  st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);  
164  if (st == noErr) {
165    SecKeychainItemFreeContent(ptr, outData);
166    if (st2 == noErr) {
167      SecKeychainItemFreeAttributesAndData(attrList, outData2);
168    }
169  } 
170  return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}}
171}
172
173int foo() {
174  unsigned int *ptr = 0;
175  OSStatus st = 0;
176
177  UInt32 length;
178  void *outData;
179
180  st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
181  if (st == noErr)
182    SecKeychainItemFreeContent(ptr, outData);
183
184  return 0;
185}// no-warning
186