asn1_item_embed_new(): if locking failed, don't call asn1_item_embed_free()
[openssl.git] / crypto / asn1 / tasn_new.c
index 455a88ab62824d6a8317f980b04c97db7ace5f2f..11c804026adc0b434e9b6e588e35aa2496312e77 100644 (file)
@@ -100,7 +100,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
         }
         asn1_set_choice_selector(pval, -1, it);
         if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
-            goto auxerr;
+            goto auxerr2;
         break;
 
     case ASN1_ITYPE_NDEF_SEQUENCE:
@@ -123,15 +123,22 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
             if (*pval == NULL)
                 goto memerr;
         }
-        asn1_do_lock(pval, 0, it);
+        /* 0 : init. lock */
+        if (asn1_do_lock(pval, 0, it) < 0) {
+            if (!embed) {
+                OPENSSL_free(*pval);
+                *pval = NULL;
+            }
+            goto memerr;
+        }
         asn1_enc_init(pval, it);
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
             pseqval = asn1_get_field_ptr(pval, tt);
             if (!asn1_template_new(pseqval, tt))
-                goto memerr;
+                goto memerr2;
         }
         if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
-            goto auxerr;
+            goto auxerr2;
         break;
     }
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
@@ -139,6 +146,8 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 #endif
     return 1;
 
+ memerr2:
+    asn1_item_embed_free(pval, it, embed);
  memerr:
     ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
@@ -146,9 +155,10 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 #endif
     return 0;
 
+ auxerr2:
+    asn1_item_embed_free(pval, it, embed);
  auxerr:
     ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
-    ASN1_item_ex_free(pval, it);
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     OPENSSL_mem_debug_pop();
 #endif
@@ -261,8 +271,14 @@ static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
 
     if (it->funcs) {
         const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
-        if (pf->prim_new)
+        if (embed) {
+            if (pf->prim_clear) {
+                pf->prim_clear(pval, it);
+                return 1;
+            }
+        } else if (pf->prim_new) {
             return pf->prim_new(pval, it);
+        }
     }
 
     if (it->itype == ASN1_ITYPE_MSTRING)