Commit 72d66a5ca0 for openssl.org
commit 72d66a5ca0ba30f81d268e0e62405efa45c8a37a
Author: Greensi7 <adam.tabak04@gmail.com>
Date: Thu Sep 10 00:48:13 2026 +0200
Fix memory leaks from duplicate X509v3 section fields
A failed lhash insertion during NCONF_load_bio() can leave duplicate
fields in a section stack. Some X509v3 parsers assume these fields are
unique and overwrite allocated values causing memory leaks.
Also fix bug where missing policyid is assumed to be present.
If policyid was not specified old code checked it against NULL
which is incorrect because it is initialized to OBJ_nid2obj(NID_undef)
not to NULL.
Example 1 (crypto/x509/v3_cpols.c): *only under MFAIL
```
[default]
certificatePolicies = @policy
[policy]
policyIdentifier = 1.2.3.4.5.6
policyIdentifier = 1.2.3.4.5.7
```
Example 2 (crypto/x509/v3_cpols.c): *only under MFAIL
```
[default]
certificatePolicies = @policy
[policy]
policyIdentifier = 1.2.3.4.5.6
userNotice = @notice
[notice]
explicitText = first
explicitText = second
```
Example 3 (crypto/x509/v3_crld.c): *only under MFAIL
```
[default]
crlDistributionPoints = point
[point]
CRLissuer = DNS:first.example
CRLissuer = DNS:second.example
```
Found by: x509v3 fuzzer
Assisted-by: ChatGPT:gpt-5.6
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
Reviewed-by: Norbert Pocs <norbertp@openssl.org>
Merge-date: Fri Oct 2 08:45:38 2026
Merged-from: https://github.com/openssl/openssl/pull/32792
diff --git a/crypto/x509/v3_cpols.c b/crypto/x509/v3_cpols.c
index 0414f3d387..dd164426a5 100644
--- a/crypto/x509/v3_cpols.c
+++ b/crypto/x509/v3_cpols.c
@@ -168,6 +168,7 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *polstrs, int ia5org)
{
int i;
+ int policyid_seen = 0;
CONF_VALUE *cnf;
POLICYINFO *pol;
POLICYQUALINFO *qual;
@@ -181,12 +182,18 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
if (strcmp(cnf->name, "policyIdentifier") == 0) {
ASN1_OBJECT *pobj;
+ if (policyid_seen) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_DUPLICATE_FIELD,
+ "field=%s", cnf->name);
+ goto err;
+ }
if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
X509V3_conf_err(cnf);
goto err;
}
pol->policyid = pobj;
+ policyid_seen = 1;
} else if (!ossl_v3_name_cmp(cnf->name, "CPS")) {
if (pol->qualifiers == NULL)
@@ -243,7 +250,7 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
goto err;
}
}
- if (pol->policyid == NULL) {
+ if (!policyid_seen) {
ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
goto err;
}
@@ -316,6 +323,11 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
value = cnf->value;
if (strcmp(cnf->name, "explicitText") == 0) {
+ if (not->exptext != NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_DUPLICATE_FIELD,
+ "field=%s", cnf->name);
+ goto err;
+ }
tag = displaytext_str2tag(value, &tag_len);
if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c
index 0a5daae747..ebd475eda1 100644
--- a/crypto/x509/v3_crld.c
+++ b/crypto/x509/v3_crld.c
@@ -226,6 +226,11 @@ static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
if (!set_reasons(&point->reasons, cnf->value))
goto err;
} else if (strcmp(cnf->name, "CRLissuer") == 0) {
+ if (point->CRLissuer != NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_DUPLICATE_FIELD,
+ "field=%s", cnf->name);
+ goto err;
+ }
point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
if (point->CRLissuer == NULL)
goto err;