From 05a952dbb9ddb92cbbc518eddeb04bdffd1d0a90 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 10 Mar 2021 19:14:27 -0600 Subject: [PATCH] asn1: Fix IMPLICIT tagging (codegen) --- lib/asn1/gen.c | 35 +++++++++++++++++++++++++++++++++++ lib/asn1/gen_decode.c | 2 +- lib/asn1/gen_encode.c | 2 +- lib/asn1/gen_length.c | 2 +- lib/asn1/gen_locl.h | 1 + 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/asn1/gen.c b/lib/asn1/gen.c index b47bb30e9..e60a3cfca 100644 --- a/lib/asn1/gen.c +++ b/lib/asn1/gen.c @@ -551,6 +551,41 @@ generate_constant (const Symbol *s) } } +int +is_tagged_type(const Type *t) +{ + /* + * Start by chasing aliasings like this: + * + * Type0 ::= ... + * Type1 ::= Type0 + * .. + * TypeN ::= TypeN-1 + * + * to , then check if is tagged. + */ + while (t->type == TType) { + if (t->subtype) + t = t->subtype; + else if (t->symbol && t->symbol->type) + t = t->symbol->type; + else + abort(); + + } + if (t->type == TTag && t->tag.tagenv == TE_EXPLICIT) + return 1; + if (t->type == TTag) { + if (t->subtype) + return is_tagged_type(t->subtype); + if (t->symbol && t->symbol->type) + return is_tagged_type(t->symbol->type); + /* This is the tag */ + return 1; + } + return 0; +} + int is_primitive_type(const Type *t) { diff --git a/lib/asn1/gen_decode.c b/lib/asn1/gen_decode.c index 54579384d..6c8762fe0 100644 --- a/lib/asn1/gen_decode.c +++ b/lib/asn1/gen_decode.c @@ -533,7 +533,7 @@ decode_type(const char *name, const Type *t, int optional, struct value *defval, else if (t->subtype->symbol && strcmp(t->subtype->symbol->name, "HEIM_ANY")) replace_tag = 1; } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol) - replace_tag = 1; + replace_tag = is_tagged_type(t->subtype->symbol->type); if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL) errx(1, "malloc"); diff --git a/lib/asn1/gen_encode.c b/lib/asn1/gen_encode.c index 43cf04926..b0123a8be 100644 --- a/lib/asn1/gen_encode.c +++ b/lib/asn1/gen_encode.c @@ -457,7 +457,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr) * functions, and those will be adding their UNIVERSAL or whatever * tags unlike our raw primtive codec library. */ - replace_tag = 1; + replace_tag = is_tagged_type(t->subtype->symbol->type); if (replace_tag) fprintf(codefile, diff --git a/lib/asn1/gen_length.c b/lib/asn1/gen_length.c index 01086baad..ab5c5f390 100644 --- a/lib/asn1/gen_length.c +++ b/lib/asn1/gen_length.c @@ -266,7 +266,7 @@ length_type (const char *name, const Type *t, else if (t->subtype->symbol && strcmp(t->subtype->symbol->name, "heim_any")) replace_tag = 1; } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol) - replace_tag = 1; + replace_tag = is_tagged_type(t->subtype->symbol->type); if (replace_tag) /* * We're replacing the tag of the underlying type. If that type is diff --git a/lib/asn1/gen_locl.h b/lib/asn1/gen_locl.h index aaed75a70..3575d62a9 100644 --- a/lib/asn1/gen_locl.h +++ b/lib/asn1/gen_locl.h @@ -138,6 +138,7 @@ void add_export(const char *); int is_export(const char *); int yyparse(void); int is_primitive_type(const Type *); +int is_tagged_type(const Type *); int preserve_type(const char *); int seq_type(const char *);