CVE-2017-5334: Double Free (CWE-415)
value: Double free vulnerability in the gnutls_x509_ext_import_proxy function in GnuTLS before 3.3.26 and 3.5.x before 3.5.8 allows remote attackers to have unspecified impact via crafted policy language information in an X.509 certificate with a Proxy Certificate Information extension.
CWE description: The product calls free() twice on the same memory address, potentially leading to modification of unexpected memory locations.
CVSS v3 base score: 9.8
Published: 2017-03-24T15:59Z
Repository: https://gitlab.com/gnutls/gnutls
Language: C
Files changed: lib/x509/x509_ext.c
Commit date: 2016-12-16 14:05:32 +0000
Commit message: gnutls_x509_ext_import_proxy: fix issue reading the policy language

If the language was set but the policy wasn't, that could lead to
a double free, as the value returned to the user was freed.

Diff: diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c
index f7c7346728..2cbb684691 100644
--- a/lib/x509/x509_ext.c
+++ b/lib/x509/x509_ext.c
@@ -1447,11 +1447,12 @@ int gnutls_x509_ext_import_proxy(const gnutls_datum_t * ext, int *pathlen,
 			      char **policyLanguage, char **policy,
 			      size_t * sizeof_policy)
 {
 	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
 	int result;
-	gnutls_datum_t value = { NULL, 0 };
+	gnutls_datum_t value1 = { NULL, 0 };
+	gnutls_datum_t value2 = { NULL, 0 };
 
 	if ((result = asn1_create_element
 	     (_gnutls_get_pkix(), "PKIX1.ProxyCertInfo",
 	      &c2)) != ASN1_SUCCESS) {
 		gnutls_assert();
@@ -1477,44 +1478,43 @@ int gnutls_x509_ext_import_proxy(const gnutls_datum_t * ext, int *pathlen,
 			goto cleanup;
 		}
 	}
 
 	result = _gnutls_x509_read_value(c2, "proxyPolicy.policyLanguage",
-					 &value);
+					 &value1);
 	if (result < 0) {
 		gnutls_assert();
 		goto cleanup;
 	}
 
 	if (policyLanguage) {
-		*policyLanguage = (char *)value.data;
-	} else {
-		gnutls_free(value.data);
-		value.data = NULL;
+		*policyLanguage = (char *)value1.data;
+		value1.data = NULL;
 	}
 
-	result = _gnutls_x509_read_value(c2, "proxyPolicy.policy", &value);
+	result = _gnutls_x509_read_value(c2, "proxyPolicy.policy", &value2);
 	if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
 		if (policy)
 			*policy = NULL;
 		if (sizeof_policy)
 			*sizeof_policy = 0;
 	} else if (result < 0) {
 		gnutls_assert();
 		goto cleanup;
 	} else {
 		if (policy) {
-			*policy = (char *)value.data;
-			value.data = NULL;
+			*policy = (char *)value2.data;
+			value2.data = NULL;
 		}
 		if (sizeof_policy)
-			*sizeof_policy = value.size;
+			*sizeof_policy = value2.size;
 	}
 
 	result = 0;
  cleanup:
-	gnutls_free(value.data);
+	gnutls_free(value1.data);
+	gnutls_free(value2.data);
 	asn1_delete_structure(&c2);
 
 	return result;
 }
 

Vulnerable code: 	gnutls_datum_t value = { NULL, 0 };
					 &value);
		*policyLanguage = (char *)value.data;
	} else {
		gnutls_free(value.data);
		value.data = NULL;
	result = _gnutls_x509_read_value(c2, "proxyPolicy.policy", &value);
			*policy = (char *)value.data;
			value.data = NULL;
			*sizeof_policy = value.size;
	gnutls_free(value.data);
Fixed code: 	gnutls_datum_t value1 = { NULL, 0 };
	gnutls_datum_t value2 = { NULL, 0 };
					 &value1);
		*policyLanguage = (char *)value1.data;
		value1.data = NULL;
	result = _gnutls_x509_read_value(c2, "proxyPolicy.policy", &value2);
			*policy = (char *)value2.data;
			value2.data = NULL;
			*sizeof_policy = value2.size;
	gnutls_free(value1.data);
	gnutls_free(value2.data);