Fix embedded string handling.
authorDr. Stephen Henson <steve@openssl.org>
Sun, 2 Oct 2016 13:13:40 +0000 (14:13 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 17 Oct 2016 13:36:29 +0000 (14:36 +0100)
Don't rely on embedded flag to free strings correctly: it wont be
set if there is a malloc failure during initialisation.

Thanks to Guido Vranken for reporting this issue.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1725)
(cherry picked from commit 6215f27a83c6b9089a217dd6deab1665e0ced516)

crypto/asn1/a_type.c
crypto/asn1/asn1_lib.c
crypto/asn1/asn1_locl.h
crypto/asn1/tasn_fre.c

index 42dbcbfffca4524c41e9a8ca0ba349139516f85a..df42360e76101b2862333b6b479e36b4f27071e3 100644 (file)
@@ -25,7 +25,7 @@ void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
 {
     if (a->value.ptr != NULL) {
         ASN1_TYPE **tmp_a = &a;
-        asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
+        asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
     }
     a->type = type;
     if (type == V_ASN1_BOOLEAN)
index 9dfe395399c58bc2479146312d7762f6b4b27bc8..8ca53b4ce4f7c85974edf257a8de7398ad2f93cf 100644 (file)
@@ -11,6 +11,7 @@
 #include <limits.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
+#include "asn1_locl.h"
 
 static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
                            long max);
@@ -314,16 +315,23 @@ ASN1_STRING *ASN1_STRING_type_new(int type)
     return (ret);
 }
 
-void ASN1_STRING_free(ASN1_STRING *a)
+void asn1_string_embed_free(ASN1_STRING *a, int embed)
 {
     if (a == NULL)
         return;
     if (!(a->flags & ASN1_STRING_FLAG_NDEF))
         OPENSSL_free(a->data);
-    if (!(a->flags & ASN1_STRING_FLAG_EMBED))
+    if (embed == 0)
         OPENSSL_free(a);
 }
 
+void ASN1_STRING_free(ASN1_STRING *a)
+{
+    if (a == NULL)
+        return;
+    asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
+}
+
 void ASN1_STRING_clear_free(ASN1_STRING *a)
 {
     if (a == NULL)
index 56c99541d5f40d9cf68bdc3adc9ba4aec73fc1fe..5f597bd98f9c4807a7ecc94bf465b4be367145bb 100644 (file)
@@ -45,6 +45,8 @@ DEFINE_STACK_OF(MIME_HEADER)
 /* Month values for printing out times */
 extern const char *_asn1_mon[12];
 
+void asn1_string_embed_free(ASN1_STRING *a, int embed);
+
 int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
 int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
                              const ASN1_ITEM *it);
@@ -63,7 +65,7 @@ int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
 int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
                   const ASN1_ITEM *it);
 
-void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
 void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
 
 ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
index f730d110bf929aa77e2ba7bf4c4dcbfe54ccaa35..3c98efb363c431688acbd1ac4f0cc015e53ce283 100644 (file)
@@ -52,11 +52,11 @@ static void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
         if (it->templates)
             asn1_template_free(pval, it->templates);
         else
-            asn1_primitive_free(pval, it);
+            asn1_primitive_free(pval, it, embed);
         break;
 
     case ASN1_ITYPE_MSTRING:
-        asn1_primitive_free(pval, it);
+        asn1_primitive_free(pval, it, embed);
         break;
 
     case ASN1_ITYPE_CHOICE:
@@ -147,7 +147,7 @@ void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
     }
 }
 
-void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 {
     int utype;
 
@@ -195,12 +195,12 @@ void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
         break;
 
     case V_ASN1_ANY:
-        asn1_primitive_free(pval, NULL);
+        asn1_primitive_free(pval, NULL, 0);
         OPENSSL_free(*pval);
         break;
 
     default:
-        ASN1_STRING_free((ASN1_STRING *)*pval);
+        asn1_string_embed_free((ASN1_STRING *)*pval, embed);
         break;
     }
     *pval = NULL;