keychainAPI.m revision f7ce52b0995efd65d51a3359939c09022a23e04c
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{{Call to free data when error was returned during allocation.}} 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; 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 104void 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. 122void fooOnlyFreeParam(void *attrList, void* X) { 123 SecKeychainItemFreeContent(attrList, X); 124}// no-warning 125 126// If we are returning the value, do not report. 127void* 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 136// Password was passed in as an argument and does nt have to be deleted. 137OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) { 138 OSStatus err; 139 SecKeychainItemRef item; 140 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx", 141 passwordLength, password, &item); 142 return err; 143} // no-warning 144 145// Make sure we do not report an error if we call free only if password != 0. 146OSStatus testSecKeychainFindGenericPassword(UInt32* passwordLength) { 147 OSStatus err; 148 SecKeychainItemRef item; 149 void *password; 150 err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx", 151 passwordLength, &password, &item); 152 if (err == noErr && password) { 153 SecKeychainItemFreeContent(0, password); 154 } 155 return err; 156} 157 158int apiMismatch(SecKeychainItemRef itemRef, 159 SecKeychainAttributeInfo *info, 160 SecItemClass *itemClass) { 161 OSStatus st = 0; 162 SecKeychainAttributeList *attrList; 163 UInt32 length; 164 void *outData; 165 166 st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, 167 &attrList, &length, &outData); 168 if (st == noErr) 169 SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Allocator doesn't match the deallocator}} 170 return 0; 171} 172 173int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef, 174 SecKeychainAttributeInfo *info, 175 SecItemClass *itemClass) { 176 unsigned int *ptr = 0; 177 OSStatus st = 0; 178 UInt32 length; 179 void *outData; 180 OSStatus st2 = 0; 181 SecKeychainAttributeList *attrList; 182 UInt32 length2; 183 void *outData2; 184 185 st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, 186 &attrList, &length2, &outData2); 187 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); 188 if (st == noErr) { 189 SecKeychainItemFreeContent(ptr, outData); 190 if (st2 == noErr) { 191 SecKeychainItemFreeAttributesAndData(attrList, outData2); 192 } 193 } 194 return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}} 195} 196 197int foo(CFTypeRef keychainOrArray, SecProtocolType protocol, 198 SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) { 199 unsigned int *ptr = 0; 200 OSStatus st = 0; 201 202 UInt32 length; 203 void *outData[5]; 204 205 st = SecKeychainFindInternetPassword(keychainOrArray, 206 16, "server", 16, "domain", 16, "account", 207 16, "path", 222, protocol, authenticationType, 208 &length, &(outData[3]), itemRef); 209 if (length == 5) { 210 if (st == noErr) 211 SecKeychainItemFreeContent(ptr, outData[3]); 212 } 213 if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}} 214 length++; 215 } 216 return 0; 217}// no-warning 218