keychainAPI.m revision ca0b57e07cfa029d4a6a061260727625bd833fd4
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; 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, no 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 136int apiMismatch(SecKeychainItemRef itemRef, 137 SecKeychainAttributeInfo *info, 138 SecItemClass *itemClass) { 139 OSStatus st = 0; 140 SecKeychainAttributeList *attrList; 141 UInt32 length; 142 void *outData; 143 144 st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, 145 &attrList, &length, &outData); 146 if (st == noErr) 147 SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Allocator doesn't match the deallocator}} 148 return 0; 149} 150 151int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef, 152 SecKeychainAttributeInfo *info, 153 SecItemClass *itemClass) { 154 unsigned int *ptr = 0; 155 OSStatus st = 0; 156 UInt32 length; 157 void *outData; 158 OSStatus st2 = 0; 159 SecKeychainAttributeList *attrList; 160 UInt32 length2; 161 void *outData2; 162 163 st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, 164 &attrList, &length2, &outData2); 165 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); 166 if (st == noErr) { 167 SecKeychainItemFreeContent(ptr, outData); 168 if (st2 == noErr) { 169 SecKeychainItemFreeAttributesAndData(attrList, outData2); 170 } 171 } 172 return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}} 173} 174 175int foo() { 176 unsigned int *ptr = 0; 177 OSStatus st = 0; 178 179 UInt32 length; 180 void *outData; 181 182 st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); 183 if (st == noErr) 184 SecKeychainItemFreeContent(ptr, outData); 185 186 return 0; 187}// no-warning 188