Commit b43a9e6657120fdfb3d01e603aac4c006de98477

Patrick Steinhardt 2020-05-15T17:46:24

streams: openssl: fix memleak due to us not free'ing certs When creating a `git_cert` from the OpenSSL X509 certificate of a given stream, we do not call `X509_free()` on the certificate, leading to a memory leak as soon as the certificate is requested e.g. by the certificate check callback. Fix the issue by properly calling `X509_free()`.

diff --git a/src/streams/openssl.c b/src/streams/openssl.c
index 5b66352..6a490d1 100644
--- a/src/streams/openssl.c
+++ b/src/streams/openssl.c
@@ -655,15 +655,16 @@ static int openssl_connect(git_stream *stream)
 static int openssl_certificate(git_cert **out, git_stream *stream)
 {
 	openssl_stream *st = (openssl_stream *) stream;
-	int len;
 	X509 *cert = SSL_get_peer_certificate(st->ssl);
-	unsigned char *guard, *encoded_cert;
+	unsigned char *guard, *encoded_cert = NULL;
+	int error, len;
 
 	/* Retrieve the length of the certificate first */
 	len = i2d_X509(cert, NULL);
 	if (len < 0) {
 		git_error_set(GIT_ERROR_NET, "failed to retrieve certificate information");
-		return -1;
+		error = -1;
+		goto out;
 	}
 
 	encoded_cert = git__malloc(len);
@@ -673,18 +674,23 @@ static int openssl_certificate(git_cert **out, git_stream *stream)
 
 	len = i2d_X509(cert, &guard);
 	if (len < 0) {
-		git__free(encoded_cert);
 		git_error_set(GIT_ERROR_NET, "failed to retrieve certificate information");
-		return -1;
+		error = -1;
+		goto out;
 	}
 
 	st->cert_info.parent.cert_type = GIT_CERT_X509;
 	st->cert_info.data = encoded_cert;
 	st->cert_info.len = len;
+	encoded_cert = NULL;
 
 	*out = &st->cert_info.parent;
+	error = 0;
 
-	return 0;
+out:
+	git__free(encoded_cert);
+	X509_free(cert);
+	return error;
 }
 
 static int openssl_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts)