ansasaki / rpms / gnutls

Forked from rpms/gnutls 5 years ago
Clone
Blob Blame History Raw
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index 9b7047a..8cd9fd3 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -53,8 +53,8 @@ extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
 void *_gnutls_file_mutex;
 void *_gnutls_pkcs11_mutex;
 
-ASN1_TYPE _gnutls_pkix1_asn;
-ASN1_TYPE _gnutls_gnutls_asn;
+ASN1_TYPE _gnutls_pkix1_asn = ASN1_TYPE_EMPTY;
+ASN1_TYPE _gnutls_gnutls_asn = ASN1_TYPE_EMPTY;
 
 gnutls_log_func _gnutls_log_func = NULL;
 gnutls_audit_log_func _gnutls_audit_log_func = NULL;
@@ -166,6 +166,9 @@ gnutls_global_set_mem_functions(gnutls_alloc_function alloc_func,
 GNUTLS_STATIC_MUTEX(global_init_mutex);
 static int _gnutls_init = 0;
 
+/* cache the return code */
+static int _gnutls_init_ret = 0;
+
 /**
  * gnutls_global_init:
  *
@@ -186,6 +189,9 @@ static int _gnutls_init = 0;
  * do not support library constructors and static linking. This
  * function also became thread safe.
  *
+ * A subsequent call of this function if the initial has failed will
+ * return the same error code.
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
  *   otherwise a negative error code is returned.
  **/
@@ -199,7 +205,7 @@ int gnutls_global_init(void)
 
 	_gnutls_init++;
 	if (_gnutls_init > 1) {
-		ret = 0;
+		ret = _gnutls_init_ret;
 		goto out;
 	}
 
@@ -235,14 +241,17 @@ int gnutls_global_init(void)
 		goto out;
 	}
 
+	_gnutls_pkix1_asn = ASN1_TYPE_EMPTY;
 	res = asn1_array2tree(pkix_asn1_tab, &_gnutls_pkix1_asn, NULL);
 	if (res != ASN1_SUCCESS) {
+		gnutls_assert();
 		ret = _gnutls_asn2err(res);
 		goto out;
 	}
 
 	res = asn1_array2tree(gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL);
 	if (res != ASN1_SUCCESS) {
+		gnutls_assert();
 		ret = _gnutls_asn2err(res);
 		goto out;
 	}
@@ -306,6 +315,7 @@ int gnutls_global_init(void)
 	ret = 0;
 
       out:
+	_gnutls_init_ret = ret;
 	GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
 	return ret;
 }
@@ -316,11 +326,19 @@ static void _gnutls_global_deinit(unsigned destructor)
 
 	if (_gnutls_init == 1) {
 		_gnutls_init = 0;
+		if (_gnutls_init_ret < 0) {
+			/* only deinitialize if gnutls_global_init() has
+			 * succeeded */
+			gnutls_assert();
+			goto fail;
+		}
+
 		gnutls_crypto_deinit();
 		_gnutls_rnd_deinit();
 		_gnutls_ext_deinit();
 		asn1_delete_structure(&_gnutls_gnutls_asn);
 		asn1_delete_structure(&_gnutls_pkix1_asn);
+
 		_gnutls_crypto_deregister();
 		gnutls_system_global_deinit();
 		_gnutls_cryptodev_deinit();
@@ -341,6 +359,8 @@ static void _gnutls_global_deinit(unsigned destructor)
 		if (_gnutls_init > 0)
 			_gnutls_init--;
 	}
+
+ fail:
 	GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
 }