summaryrefslogtreecommitdiff
path: root/clang/test/Analysis/keychainAPI.m
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/Analysis/keychainAPI.m')
-rw-r--r--clang/test/Analysis/keychainAPI.m409
1 files changed, 409 insertions, 0 deletions
diff --git a/clang/test/Analysis/keychainAPI.m b/clang/test/Analysis/keychainAPI.m
new file mode 100644
index 0000000..cb4f72c
--- /dev/null
+++ b/clang/test/Analysis/keychainAPI.m
@@ -0,0 +1,409 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=osx.SecKeychainAPI %s -analyzer-ipa=inlining -verify
+
+// Fake typedefs.
+typedef unsigned int OSStatus;
+typedef unsigned int SecKeychainAttributeList;
+typedef unsigned int SecKeychainItemRef;
+typedef unsigned int SecItemClass;
+typedef unsigned int UInt32;
+typedef unsigned int CFTypeRef;
+typedef unsigned int UInt16;
+typedef unsigned int SecProtocolType;
+typedef unsigned int SecAuthenticationType;
+typedef unsigned int SecKeychainAttributeInfo;
+enum {
+ noErr = 0,
+ GenericError = 1
+};
+
+// Functions that allocate data.
+OSStatus SecKeychainItemCopyContent (
+ SecKeychainItemRef itemRef,
+ SecItemClass *itemClass,
+ SecKeychainAttributeList *attrList,
+ UInt32 *length,
+ void **outData
+);
+OSStatus SecKeychainFindGenericPassword (
+ CFTypeRef keychainOrArray,
+ UInt32 serviceNameLength,
+ const char *serviceName,
+ UInt32 accountNameLength,
+ const char *accountName,
+ UInt32 *passwordLength,
+ void **passwordData,
+ SecKeychainItemRef *itemRef
+);
+OSStatus SecKeychainFindInternetPassword (
+ CFTypeRef keychainOrArray,
+ UInt32 serverNameLength,
+ const char *serverName,
+ UInt32 securityDomainLength,
+ const char *securityDomain,
+ UInt32 accountNameLength,
+ const char *accountName,
+ UInt32 pathLength,
+ const char *path,
+ UInt16 port,
+ SecProtocolType protocol,
+ SecAuthenticationType authenticationType,
+ UInt32 *passwordLength,
+ void **passwordData,
+ SecKeychainItemRef *itemRef
+);
+OSStatus SecKeychainItemCopyAttributesAndData (
+ SecKeychainItemRef itemRef,
+ SecKeychainAttributeInfo *info,
+ SecItemClass *itemClass,
+ SecKeychainAttributeList **attrList,
+ UInt32 *length,
+ void **outData
+);
+
+// Functions which free data.
+OSStatus SecKeychainItemFreeContent (
+ SecKeychainAttributeList *attrList,
+ void *data
+);
+OSStatus SecKeychainItemFreeAttributesAndData (
+ SecKeychainAttributeList *attrList,
+ void *data
+);
+
+void errRetVal() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ if (st == GenericError) // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}}
+ SecKeychainItemFreeContent(ptr, outData); // expected-warning{{Only call free if a valid (non-NULL) buffer was returned}}
+}
+
+// If null is passed in, the data is not allocated, so no need for the matching free.
+void fooDoNotReportNull() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 *length = 0;
+ void **outData = 0;
+ SecKeychainItemCopyContent(2, ptr, ptr, 0, 0);
+ SecKeychainItemCopyContent(2, ptr, ptr, length, outData);
+}// no-warning
+
+void doubleAlloc() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); // expected-warning {{Allocated data should be released before another call to the allocator:}}
+ if (st == noErr)
+ SecKeychainItemFreeContent(ptr, outData);
+}
+
+void fooOnlyFree() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData = &length;
+ SecKeychainItemFreeContent(ptr, outData);// expected-warning{{Trying to free data which has not been allocated}}
+}
+
+// Do not warn if undefined value is passed to a function.
+void fooOnlyFreeUndef() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ SecKeychainItemFreeContent(ptr, outData);
+}// no-warning
+
+// Do not warn if the address is a parameter in the enclosing function.
+void fooOnlyFreeParam(void *attrList, void* X) {
+ SecKeychainItemFreeContent(attrList, X);
+}// no-warning
+
+// If we are returning the value, do not report.
+void* returnContent() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ return outData;
+} // no-warning
+
+// Password was passed in as an argument and does not have to be deleted.
+OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) {
+ OSStatus err;
+ SecKeychainItemRef item;
+ err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
+ passwordLength, password, &item);
+ return err;
+} // no-warning
+
+// Make sure we do not report an error if we call free only if password != 0.
+// Also, do not report double allocation if first allocation returned an error.
+OSStatus testSecKeychainFindGenericPassword(UInt32* passwordLength,
+ CFTypeRef keychainOrArray, SecProtocolType protocol,
+ SecAuthenticationType authenticationType) {
+ OSStatus err;
+ SecKeychainItemRef item;
+ void *password;
+ err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
+ passwordLength, &password, &item);
+ if( err == GenericError ) {
+ err = SecKeychainFindInternetPassword(keychainOrArray,
+ 16, "server", 16, "domain", 16, "account",
+ 16, "path", 222, protocol, authenticationType,
+ passwordLength, &(password), 0);
+ }
+
+ if (err == noErr && password) {
+ SecKeychainItemFreeContent(0, password);
+ }
+ return err;
+}
+
+int apiMismatch(SecKeychainItemRef itemRef,
+ SecKeychainAttributeInfo *info,
+ SecItemClass *itemClass) {
+ OSStatus st = 0;
+ SecKeychainAttributeList *attrList;
+ UInt32 length;
+ void *outData;
+
+ st = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
+ &attrList, &length, &outData);
+ if (st == noErr)
+ SecKeychainItemFreeContent(attrList, outData); // expected-warning{{Deallocator doesn't match the allocator}}
+ return 0;
+}
+
+int ErrorCodesFromDifferentAPISDoNotInterfere(SecKeychainItemRef itemRef,
+ SecKeychainAttributeInfo *info,
+ SecItemClass *itemClass) {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ OSStatus st2 = 0;
+ SecKeychainAttributeList *attrList;
+ UInt32 length2;
+ void *outData2;
+
+ st2 = SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass,
+ &attrList, &length2, &outData2);
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ if (st == noErr) {
+ SecKeychainItemFreeContent(ptr, outData);
+ if (st2 == noErr) {
+ SecKeychainItemFreeAttributesAndData(attrList, outData2);
+ }
+ }
+ return 0; // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeAttributesAndData'}}
+}
+
+int foo(CFTypeRef keychainOrArray, SecProtocolType protocol,
+ SecAuthenticationType authenticationType, SecKeychainItemRef *itemRef) {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+
+ UInt32 length;
+ void *outData[5];
+
+ st = SecKeychainFindInternetPassword(keychainOrArray,
+ 16, "server", 16, "domain", 16, "account",
+ 16, "path", 222, protocol, authenticationType,
+ &length, &(outData[3]), itemRef);
+ if (length == 5) {
+ if (st == noErr)
+ SecKeychainItemFreeContent(ptr, outData[3]);
+ }
+ if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}}
+ length++;
+ }
+ return 0;
+}// no-warning
+
+void free(void *ptr);
+void deallocateWithFree() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ if (st == noErr)
+ free(outData); // expected-warning{{Deallocator doesn't match the allocator: 'SecKeychainItemFreeContent' should be used}}
+}
+
+// Typesdefs for CFStringCreateWithBytesNoCopy.
+typedef char uint8_t;
+typedef signed long CFIndex;
+typedef UInt32 CFStringEncoding;
+typedef unsigned Boolean;
+typedef const struct __CFString * CFStringRef;
+typedef const struct __CFAllocator * CFAllocatorRef;
+extern const CFAllocatorRef kCFAllocatorDefault;
+extern const CFAllocatorRef kCFAllocatorSystemDefault;
+extern const CFAllocatorRef kCFAllocatorMalloc;
+extern const CFAllocatorRef kCFAllocatorMallocZone;
+extern const CFAllocatorRef kCFAllocatorNull;
+extern const CFAllocatorRef kCFAllocatorUseContext;
+CFStringRef CFStringCreateWithBytesNoCopy(CFAllocatorRef alloc, const uint8_t *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean externalFormat, CFAllocatorRef contentsDeallocator);
+extern void CFRelease(CFStringRef cf);
+
+void DellocWithCFStringCreate1(CFAllocatorRef alloc) {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *bytes;
+ char * x;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
+ if (st == noErr) {
+ CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorDefault); // expected-warning{{Deallocator doesn't match the allocator:}}
+ CFRelease(userStr);
+ }
+}
+
+void DellocWithCFStringCreate2(CFAllocatorRef alloc) {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *bytes;
+ char * x;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
+ if (st == noErr) {
+ CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); // expected-warning{{Allocated data is not released}}
+ CFRelease(userStr);
+ }
+}
+
+void DellocWithCFStringCreate3(CFAllocatorRef alloc) {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *bytes;
+ char * x;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
+ if (st == noErr) {
+ CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorUseContext);
+ CFRelease(userStr);
+ }
+}
+
+void DellocWithCFStringCreate4(CFAllocatorRef alloc) {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *bytes;
+ char * x;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes);
+ if (st == noErr) {
+ CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, 0); // expected-warning{{Deallocator doesn't match the allocator:}}
+ CFRelease(userStr);
+ }
+}
+
+void radar10508828() {
+ UInt32 pwdLen = 0;
+ void* pwdBytes = 0;
+ OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
+#pragma unused(rc)
+ if (pwdBytes)
+ SecKeychainItemFreeContent(0, pwdBytes);
+}
+
+void radar10508828_2() {
+ UInt32 pwdLen = 0;
+ void* pwdBytes = 0;
+ OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
+ SecKeychainItemFreeContent(0, pwdBytes); // expected-warning {{Only call free if a valid (non-NULL) buffer was returned.}}
+}
+
+//Example from bug 10797.
+__inline__ static
+const char *__WBASLLevelString(int level) {
+ return "foo";
+}
+
+static int *bug10798(int *p, int columns, int prevRow) {
+ int *row = 0;
+ row = p + prevRow * columns;
+ prevRow += 2;
+ do {
+ ++prevRow;
+ row+=columns;
+ } while(10 >= row[1]);
+ return row;
+}
+
+// Test inter-procedural behaviour.
+
+void my_FreeParam(void *attrList, void* X) {
+ SecKeychainItemFreeContent(attrList, X);
+}
+
+void *my_AllocateReturn(OSStatus *st) {
+ unsigned int *ptr = 0;
+ UInt32 length;
+ void *outData;
+ *st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ return outData;
+}
+
+OSStatus my_Allocate_Param(void** password, UInt32* passwordLength) {
+ OSStatus err;
+ SecKeychainItemRef item;
+ err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx",
+ passwordLength, password, &item);
+ return err;
+}
+
+void allocAndFree1() {
+ unsigned int *ptr = 0;
+ OSStatus st = 0;
+ UInt32 length;
+ void *outData;
+ st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
+ if (st == noErr)
+ my_FreeParam(ptr, outData);
+}
+
+void consumeChar(char);
+
+void allocNoFree2(int x) {
+ OSStatus st = 0;
+ void *outData = my_AllocateReturn(&st);
+ if (x) {
+ consumeChar(*(char*)outData); // expected-warning{{Allocated data is not released:}}
+ return;
+ } else {
+ consumeChar(*(char*)outData);
+ }
+ return;
+}
+
+void allocAndFree2(void *attrList) {
+ OSStatus st = 0;
+ void *outData = my_AllocateReturn(&st);
+ if (st == noErr)
+ my_FreeParam(attrList, outData);
+}
+
+void allocNoFree3() {
+ UInt32 length = 32;
+ void *outData;
+ void *outData2;
+ OSStatus st = my_Allocate_Param(&outData, &length); // expected-warning{{Allocated data is not released}}
+ st = my_Allocate_Param(&outData2, &length); // expected-warning{{Allocated data is not released}}
+}
+
+void allocAndFree3(void *attrList) {
+ UInt32 length = 32;
+ void *outData;
+ OSStatus st = my_Allocate_Param(&outData, &length);
+ if (st == noErr)
+ SecKeychainItemFreeContent(attrList, outData);
+}
+