Commit 7cc8054673a303ee19786f347dce8caa91ce7835

Patrick Steinhardt 2018-01-03T12:54:42

streams: openssl: fix thread-safety for OpenSSL error messages The function `ERR_error_string` can be invoked without providing a buffer, in which case OpenSSL will simply return a string printed into a static buffer. Obviously and as documented in ERR_error_string(3), this is not thread-safe at all. As libgit2 is a library, though, it is easily possible that other threads may be using OpenSSL at the same time, which might lead to clobbered error strings. Fix the issue by instead using a stack-allocated buffer. According to the documentation, the caller has to provide a buffer of at least 256 bytes of size. While we do so, make sure that the buffer will never get overflown by switching to `ERR_error_string_n` to specify the buffer's size.

diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index 4a20267..6bab6b5 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -281,8 +281,9 @@ static int ssl_set_error(SSL *ssl, int error)
 	case SSL_ERROR_SYSCALL:
 		e = ERR_get_error();
 		if (e > 0) {
-			giterr_set(GITERR_NET, "SSL error: %s",
-					ERR_error_string(e, NULL));
+			char errmsg[256];
+			ERR_error_string_n(e, errmsg, sizeof(errmsg));
+			giterr_set(GITERR_NET, "SSL error: %s", errmsg);
 			break;
 		} else if (error < 0) {
 			giterr_set(GITERR_OS, "SSL error: syscall failure");
@@ -292,10 +293,13 @@ static int ssl_set_error(SSL *ssl, int error)
 		return GIT_EEOF;
 		break;
 	case SSL_ERROR_SSL:
+	{
+		char errmsg[256];
 		e = ERR_get_error();
-		giterr_set(GITERR_NET, "SSL error: %s",
-				ERR_error_string(e, NULL));
+		ERR_error_string_n(e, errmsg, sizeof(errmsg));
+		giterr_set(GITERR_NET, "SSL error: %s", errmsg);
 		break;
+	}
 	case SSL_ERROR_NONE:
 	case SSL_ERROR_ZERO_RETURN:
 	default: