Fix X509_NAME decode for malloc failures.
[openssl.git] / crypto / x509 / x_name.c
index a2eb709c8355a3cae81bc48b00ab83fe3d8686f8..c863c6921326c4abeb441def269ac67368827231 100644 (file)
@@ -125,6 +125,11 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
     *pval = NULL;
 }
 
+static void name_entry_stack_free(STACK_OF(X509_NAME_ENTRY) *ents)
+{
+    sk_X509_NAME_ENTRY_pop_free(ents, X509_NAME_ENTRY_free);
+}
+
 static int x509_name_ex_d2i(ASN1_VALUE **val,
                             const unsigned char **in, long len,
                             const ASN1_ITEM *it, int tag, int aclass,
@@ -173,25 +178,16 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
         for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
             entry = sk_X509_NAME_ENTRY_value(entries, j);
             entry->set = i;
-            if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) {
-                /*
-                 * Free all in entries if sk_X509_NAME_ENTRY_push return failure.
-                 * X509_NAME_ENTRY_free will check the null entry.
-                 */
-                sk_X509_NAME_ENTRY_pop_free(entries, X509_NAME_ENTRY_free);
+            if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
                 goto err;
-            }
-            /*
-             * If sk_X509_NAME_ENTRY_push return success, clean the entries[j].
-             * It's necessary when 'goto err;' happens.
-             */
-            sk_X509_NAME_ENTRY_set(entries, j, NULL);
         }
-        sk_X509_NAME_ENTRY_free(entries);
-        sk_STACK_OF_X509_NAME_ENTRY_set(intname.s, i, NULL);
     }
-
-    sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
+    /*
+     * All entries have now been pushed to nm->x.entries
+     * free up the stacks in intname.s but not the entries
+     * themselves.
+     */
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, sk_X509_NAME_ENTRY_free);
     intname.s = NULL;
     ret = x509_name_canon(nm.x);
     if (!ret)
@@ -202,8 +198,15 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
     return ret;
 
  err:
+    /* If intname.s is not NULL only some entries exist in nm->x.entries:
+     * zero references in nm->x.entries list. Since all entries exist
+     * in intname.s we can free them all there
+     */
+    if (intname.s != NULL) {
+        sk_X509_NAME_ENTRY_zero(nm.x->entries);
+        sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, name_entry_stack_free);
+    }
     X509_NAME_free(nm.x);
-    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, sk_X509_NAME_ENTRY_free);
     ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
     return 0;
 }
@@ -290,7 +293,7 @@ static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
                               int indent,
                               const char *fname, const ASN1_PCTX *pctx)
 {
-    if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
+    if (X509_NAME_print_ex(out, (const X509_NAME *)*pval,
                            indent, pctx->nm_flags) <= 0)
         return 0;
     return 2;
@@ -494,7 +497,7 @@ int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
     return (*xn != NULL);
 }
 
-int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
+int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
 {
     char *s, *c, *b;
     int l, i;
@@ -550,8 +553,8 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
     return 0;
 }
 
-int X509_NAME_get0_der(const unsigned char **pder, size_t *pderlen,
-                       X509_NAME *nm)
+int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
+                       size_t *pderlen)
 {
     /* Make sure encoding is valid */
     if (i2d_X509_NAME(nm, NULL) <= 0)