diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2015-09-15 15:54:19 +0100 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2015-09-16 22:17:39 +0100 |
commit | de17bd5d7f8286d8b1f0a04a3f8f5782033f5ebd (patch) | |
tree | 5fab90b0d760d271e1fe90cde99271f2407f96ed /crypto/asn1/tasn_fre.c | |
parent | 05e97f1d4f940c765e5c93771fe20820acca4438 (diff) |
New ASN.1 embed macro.
New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the
structure is not allocated: it is part of the parent. That is instead of
FOO *x;
it must be:
FOO x;
This reduces memory fragmentation and make it impossible to accidentally
set a mandatory field to NULL.
This currently only works for SEQUENCE and since it is equivalent to
ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or SEQUENCE OF.
Reviewed-by: Rich Salz <rsalz@openssl.org>
Diffstat (limited to 'crypto/asn1/tasn_fre.c')
-rw-r--r-- | crypto/asn1/tasn_fre.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index e846561e21..e219e2c0a3 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -63,15 +63,24 @@ #include <openssl/objects.h> #include "asn1_locl.h" +static void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, + int embed); + /* Free up an ASN1 structure */ void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) { - ASN1_item_ex_free(&val, it); + asn1_item_embed_free(&val, it, 0); } void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { + asn1_item_embed_free(pval, it, 0); +} + +static void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, + int embed) +{ const ASN1_TEMPLATE *tt = NULL, *seqtt; const ASN1_EXTERN_FUNCS *ef; const ASN1_AUX *aux = it->funcs; @@ -152,14 +161,22 @@ void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) } if (asn1_cb) asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); - OPENSSL_free(*pval); - *pval = NULL; + if (embed == 0) { + OPENSSL_free(*pval); + *pval = NULL; + } break; } } void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { + int embed = tt->flags & ASN1_TFLG_EMBED; + ASN1_VALUE *tval; + if (embed) { + tval = (ASN1_VALUE *)pval; + pval = &tval; + } if (tt->flags & ASN1_TFLG_SK_MASK) { STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; int i; @@ -167,12 +184,12 @@ void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i); - ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); + asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed); } sk_ASN1_VALUE_free(sk); *pval = NULL; } else { - ASN1_item_ex_free(pval, ASN1_ITEM_ptr(tt->item)); + asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed); } } |