From 6215f27a83c6b9089a217dd6deab1665e0ced516 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 2 Oct 2016 14:13:40 +0100 Subject: [PATCH] Fix embedded string handling. 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 (Merged from https://github.com/openssl/openssl/pull/1725) --- crypto/asn1/a_type.c | 2 +- crypto/asn1/asn1_lib.c | 12 ++++++++++-- crypto/asn1/asn1_locl.h | 4 +++- crypto/asn1/tasn_fre.c | 10 +++++----- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c index 42dbcbfffc..df42360e76 100644 --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -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) diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 9dfe395399..8ca53b4ce4 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -11,6 +11,7 @@ #include #include "internal/cryptlib.h" #include +#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) diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h index 56c99541d5..5f597bd98f 100644 --- a/crypto/asn1/asn1_locl.h +++ b/crypto/asn1/asn1_locl.h @@ -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, diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index f730d110bf..3c98efb363 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -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; -- 2.25.1