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

Reply via email to