summaryrefslogtreecommitdiffstats
path: root/crypto/asn1/tasn_fre.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2015-09-15 15:54:19 +0100
committerDr. Stephen Henson <steve@openssl.org>2015-09-16 22:17:39 +0100
commitde17bd5d7f8286d8b1f0a04a3f8f5782033f5ebd (patch)
tree5fab90b0d760d271e1fe90cde99271f2407f96ed /crypto/asn1/tasn_fre.c
parent05e97f1d4f940c765e5c93771fe20820acca4438 (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.c27
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);
}
}