X509_TRUST_add() and X509_PURPOSE_add() leak memory or corrupt existing
entries when they fail (ie. when memory is exhausted, or the name /
sname argument to BUF_strdup is NULL.)
This seems like an unlikely error to hit, but we may as well handle it
correctly.
Brendan
Index: libssl/src/crypto/x509/x509_trs.c
===================================================================
--- libssl.orig/src/crypto/x509/x509_trs.c
+++ libssl/src/crypto/x509/x509_trs.c
@@ -174,6 +174,7 @@ int
X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
char *name, int arg1, void *arg2)
{
+ char *tmpname = NULL;
int idx;
X509_TRUST *trtmp;
@@ -187,20 +188,22 @@ X509_TRUST_add(int id, int flags, int (*
if (idx == -1) {
if (!(trtmp = malloc(sizeof(X509_TRUST)))) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
trtmp->flags = X509_TRUST_DYNAMIC;
} else
trtmp = X509_TRUST_get0(idx);
- /* free existing name if dynamic */
- if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
- free(trtmp->name);
/* dup supplied name */
- if (!(trtmp->name = BUF_strdup(name))) {
+ if (!(tmpname = BUF_strdup(name))) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
+ /* free existing name if dynamic */
+ if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
+ free(trtmp->name);
+ trtmp->name = tmpname;
+
/* Keep the dynamic flag of existing entry */
trtmp->flags &= X509_TRUST_DYNAMIC;
/* Set all other flags */
@@ -215,14 +218,20 @@ X509_TRUST_add(int id, int flags, int (*
if (idx == -1) {
if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
if (!sk_X509_TRUST_push(trtable, trtmp)) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
}
return 1;
+
+err:
+ free(tmpname);
+ if (idx == -1)
+ free(trtmp);
+ return 0;
}
static void
Index: libssl/src/crypto/x509v3/v3_purp.c
===================================================================
--- libssl.orig/src/crypto/x509v3/v3_purp.c
+++ libssl/src/crypto/x509v3/v3_purp.c
@@ -197,6 +197,7 @@ X509_PURPOSE_add(int id, int trust, int
int (*ck)(const X509_PURPOSE *, const X509 *, int), char *name,
char *sname, void *arg)
{
+ char *tmpname = NULL, *tmpsname = NULL;
int idx;
X509_PURPOSE *ptmp;
@@ -211,24 +212,27 @@ X509_PURPOSE_add(int id, int trust, int
if (!(ptmp = malloc(sizeof(X509_PURPOSE)))) {
X509V3err(X509V3_F_X509_PURPOSE_ADD,
ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
ptmp->flags = X509_PURPOSE_DYNAMIC;
} else
ptmp = X509_PURPOSE_get0(idx);
+ /* dup supplied name */
+ tmpname = BUF_strdup(name);
+ tmpsname = BUF_strdup(sname);
+ if (!tmpname || !tmpsname) {
+ X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
/* free existing name if dynamic */
if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
free(ptmp->name);
free(ptmp->sname);
}
- /* dup supplied name */
- ptmp->name = BUF_strdup(name);
- ptmp->sname = BUF_strdup(sname);
- if (!ptmp->name || !ptmp->sname) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
- }
+ ptmp->name = tmpname;
+ ptmp->sname = tmpsname;
+
/* Keep the dynamic flag of existing entry */
ptmp->flags &= X509_PURPOSE_DYNAMIC;
/* Set all other flags */
@@ -244,15 +248,22 @@ X509_PURPOSE_add(int id, int trust, int
if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
X509V3err(X509V3_F_X509_PURPOSE_ADD,
ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
X509V3err(X509V3_F_X509_PURPOSE_ADD,
ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
}
return 1;
+
+err:
+ free(tmpname);
+ free(tmpsname);
+ if (idx == -1)
+ free(ptmp);
+ return 0;
}
static void