From 7302ee18a137f6810ef1cc40a395f99d2f46a644 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Tue, 3 Nov 2015 13:20:20 +0100
Subject: Fix potential memory leaks in Cocoa API usage

These errors were reported by Clang Analyzer.

Test-Information:

Verified that behavior is still as expected and Clang
Analyzer does not report the warnings anymore.

Change-Id: I149d75241f7680a6d2f2b6b710dd38d1ed81a209

diff --git a/SwifTools/Notifier/NotificationCenterNotifier.mm b/SwifTools/Notifier/NotificationCenterNotifier.mm
index 28cacb6..74d814e 100644
--- a/SwifTools/Notifier/NotificationCenterNotifier.mm
+++ b/SwifTools/Notifier/NotificationCenterNotifier.mm
@@ -57,23 +57,25 @@ void NotificationCenterNotifier::showMessage(Type type, const std::string& subje
 	if (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end()) {
 		return;
 	}
-
+	NSImage* image = [[NSImage alloc] initWithContentsOfFile: STD2NSSTRING(picture.string())];
 	NSUserNotification* notification = [[NSUserNotification alloc] init];
-	notification.title = STD2NSSTRING(typeToString(type));
-	notification.subtitle = STD2NSSTRING(subject);
-	notification.informativeText = STD2NSSTRING(description);
-	notification.contentImage = [[NSImage alloc] initWithContentsOfFile: STD2NSSTRING(picture.string())];
+	[notification setTitle:STD2NSSTRING(typeToString(type))];
+	[notification setSubtitle:STD2NSSTRING(subject)];
+	[notification setInformativeText:STD2NSSTRING(description)];
+	[notification setContentImage: image];
+	[image release];
 
 	// The OS X Notification Center API does not allow to attach custom data, like a pointer to a callback function,
 	// to the NSUserNotification object. Therefore we maintain a mapping from a NSUserNotification instance's identification
 	// to their respective callbacks.
-	notification.identifier = [[NSUUID UUID] UUIDString];
+	[notification setIdentifier:[[NSUUID UUID] UUIDString]];
 
 	/// \todo Currently the elements are only removed on application exit. Ideally the notifications not required anymore
 	///       are removed from the map; e.g. when visiting a chat view, all notifications from that view can be removed from
 	///       the map and the NSUserNotificationCenter.
 	p->callbacksForNotifications[NS2STDSTRING(notification.identifier)] = boost::make_shared<Context>(callback);
 	[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
+	[notification release];
 }
 
 void NotificationCenterNotifier::purgeCallbacks() {
diff --git a/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm b/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm
index 3b4e00f..4270a6f 100644
--- a/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm
+++ b/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm
@@ -38,6 +38,7 @@ SecureTransportCertificate::SecureTransportCertificate(SecCertificateRef certifi
 SecureTransportCertificate::SecureTransportCertificate(const ByteArray& der) {
 	CFDataRef derData = CFDataCreateWithBytesNoCopy(NULL, der.data(), static_cast<CFIndex>(der.size()), NULL); 
 	SecCertificateRef certificate = SecCertificateCreateWithData(NULL, derData);
+	CFRelease(derData);
 	if (certificate) {
 		certificateHandle_ = boost::shared_ptr<SecCertificate>(certificate, CFRelease);
 		parse();
@@ -57,10 +58,7 @@ void SecureTransportCertificate::parse() {
 
 	// The SecCertificateCopyValues function is not part of the iOS Secure Transport API.
 	CFDictionaryRef valueDict = SecCertificateCopyValues(certificateHandle_.get(), 0, &error);
-	if (error) {
-		CFRelease(error);
-	}
-	else {
+	if (valueDict) {
 		// Handle subject.
 		CFStringRef subject = SecCertificateCopySubjectSummary(certificateHandle_.get());
 		if (subject) {
@@ -70,11 +68,13 @@ void SecureTransportCertificate::parse() {
 		}
 
 		// Handle a single Common Name.
-		CFStringRef commonName;
+		CFStringRef commonName = NULL;
 		OSStatus error = SecCertificateCopyCommonName(certificateHandle_.get(), &commonName);
-		if (!error) {
+		if (!error && commonName) {
 			NSString* commonNameStr = bridge_cast<NSString*>(commonName);
 			commonNames_.push_back(NS2STDSTRING(commonNameStr));
+		}
+		if (commonName) {
 			CFRelease(commonName);
 		}
 
@@ -95,6 +95,10 @@ void SecureTransportCertificate::parse() {
 		}
 		CFRelease(valueDict);
 	}
+
+	if (error) {
+		CFRelease(error);
+	}
 }
 
 std::string SecureTransportCertificate::getSubjectName() const {
diff --git a/Swiften/TLS/SecureTransport/SecureTransportContext.mm b/Swiften/TLS/SecureTransport/SecureTransportContext.mm
index 7f44f7d..a702cde 100644
--- a/Swiften/TLS/SecureTransport/SecureTransportContext.mm
+++ b/Swiften/TLS/SecureTransport/SecureTransportContext.mm
@@ -38,7 +38,7 @@ namespace Swift {
 namespace {
 
 	
-CFArrayRef getClientCertificateChainAsCFArrayRef(CertificateWithKey::ref key) {
+CFArrayRef CreateClientCertificateChainAsCFArrayRef(CertificateWithKey::ref key) {
 	boost::shared_ptr<PKCS12Certificate> pkcs12 = boost::dynamic_pointer_cast<PKCS12Certificate>(key);
 	if (!key) {
 		return NULL;
@@ -64,6 +64,7 @@ CFArrayRef getClientCertificateChainAsCFArrayRef(CertificateWithKey::ref key) {
 	CFArrayRef items = NULL;
 	CFDataRef pkcs12Data = bridge_cast<CFDataRef>([NSData dataWithBytes: static_cast<const void *>(pkcs12->getData().data()) length:pkcs12->getData().size()]);
 	securityError = SecPKCS12Import(pkcs12Data, options, &items);
+	CFRelease(options);
 	NSArray* nsItems = bridge_cast<NSArray*>(items);
 
 	switch(securityError) {
@@ -76,7 +77,6 @@ CFArrayRef getClientCertificateChainAsCFArrayRef(CertificateWithKey::ref key) {
 		default:
 			CFRelease(certChain);
 			CFRelease(items);
-			CFRelease(options);
 			certChain = NULL;
 	}
 
@@ -150,7 +150,7 @@ void SecureTransportContext::setState(State newState) {
 void SecureTransportContext::connect() {
 	SWIFT_LOG_ASSERT(state_ == None, error) << "current state '" << stateToString(state_) << " invalid." << std::endl;
 	if (clientCertificate_) {
-		CFArrayRef certs = getClientCertificateChainAsCFArrayRef(clientCertificate_);
+		CFArrayRef certs = CreateClientCertificateChainAsCFArrayRef(clientCertificate_);
 		if (certs) {
 			boost::shared_ptr<CFArray> certRefs(certs, CFRelease);
 			OSStatus result = SSLSetCertificate(sslContext_.get(), certRefs.get());
@@ -274,7 +274,7 @@ void SecureTransportContext::verifyServerCertificate() {
 #pragma clang diagnostic pop
 
 bool SecureTransportContext::setClientCertificate(CertificateWithKey::ref cert) {
-	CFArrayRef nativeClientChain = getClientCertificateChainAsCFArrayRef(cert);
+	CFArrayRef nativeClientChain = CreateClientCertificateChainAsCFArrayRef(cert);
 	if (nativeClientChain) {
 		clientCertificate_ = cert;
 		CFRelease(nativeClientChain);
-- 
cgit v0.10.2-6-g49f6