LCOV - code coverage report
Current view: top level - source4/heimdal/lib/asn1 - gen_decode.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 212 375 56.5 %
Date: 2021-09-23 10:06:22 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "gen_locl.h"
      35             : #include "lex.h"
      36             : 
      37             : RCSID("$Id$");
      38             : 
      39             : static void
      40        5436 : decode_primitive (const char *typename, const char *name, const char *forwstr)
      41             : {
      42             : #if 0
      43             :     fprintf (codefile,
      44             :              "e = decode_%s(p, len, %s, &l);\n"
      45             :              "%s;\n",
      46             :              typename,
      47             :              name,
      48             :              forwstr);
      49             : #else
      50        6040 :     fprintf (codefile,
      51             :              "e = der_get_%s(p, len, %s, &l);\n"
      52             :              "if(e) %s;\np += l; len -= l; ret += l;\n",
      53             :              typename,
      54             :              name,
      55             :              forwstr);
      56             : #endif
      57        5436 : }
      58             : 
      59             : static void
      60        1213 : find_tag (const Type *t,
      61             :           Der_class *cl, Der_type *ty, unsigned *tag)
      62             : {
      63        1216 :     switch (t->type) {
      64           0 :     case TBitString:
      65           0 :         *cl  = ASN1_C_UNIV;
      66           0 :         *ty  = PRIM;
      67           0 :         *tag = UT_BitString;
      68           0 :         break;
      69           0 :     case TBoolean:
      70           0 :         *cl  = ASN1_C_UNIV;
      71           0 :         *ty  = PRIM;
      72           0 :         *tag = UT_Boolean;
      73           0 :         break;
      74           0 :     case TChoice:
      75           0 :         errx(1, "Cannot have recursive CHOICE");
      76           0 :     case TEnumerated:
      77           0 :         *cl  = ASN1_C_UNIV;
      78           0 :         *ty  = PRIM;
      79           0 :         *tag = UT_Enumerated;
      80           0 :         break;
      81           0 :     case TGeneralString:
      82           0 :         *cl  = ASN1_C_UNIV;
      83           0 :         *ty  = PRIM;
      84           0 :         *tag = UT_GeneralString;
      85           0 :         break;
      86           0 :     case TTeletexString:
      87           0 :         *cl  = ASN1_C_UNIV;
      88           0 :         *ty  = PRIM;
      89           0 :         *tag = UT_TeletexString;
      90           0 :         break;
      91           0 :     case TGeneralizedTime:
      92           0 :         *cl  = ASN1_C_UNIV;
      93           0 :         *ty  = PRIM;
      94           0 :         *tag = UT_GeneralizedTime;
      95           0 :         break;
      96           0 :     case TIA5String:
      97           0 :         *cl  = ASN1_C_UNIV;
      98           0 :         *ty  = PRIM;
      99           0 :         *tag = UT_IA5String;
     100           0 :         break;
     101           0 :     case TInteger:
     102           0 :         *cl  = ASN1_C_UNIV;
     103           0 :         *ty  = PRIM;
     104           0 :         *tag = UT_Integer;
     105           0 :         break;
     106           0 :     case TNull:
     107           0 :         *cl  = ASN1_C_UNIV;
     108           0 :         *ty  = PRIM;
     109           0 :         *tag = UT_Null;
     110           0 :         break;
     111           0 :     case TOID:
     112           0 :         *cl  = ASN1_C_UNIV;
     113           0 :         *ty  = PRIM;
     114           0 :         *tag = UT_OID;
     115           0 :         break;
     116           0 :     case TOctetString:
     117           0 :         *cl  = ASN1_C_UNIV;
     118           0 :         *ty  = PRIM;
     119           0 :         *tag = UT_OctetString;
     120           0 :         break;
     121           0 :     case TPrintableString:
     122           0 :         *cl  = ASN1_C_UNIV;
     123           0 :         *ty  = PRIM;
     124           0 :         *tag = UT_PrintableString;
     125           0 :         break;
     126           0 :     case TSequence:
     127             :     case TSequenceOf:
     128           0 :         *cl  = ASN1_C_UNIV;
     129           0 :         *ty  = CONS;
     130           0 :         *tag = UT_Sequence;
     131           0 :         break;
     132           0 :     case TSet:
     133             :     case TSetOf:
     134           0 :         *cl  = ASN1_C_UNIV;
     135           0 :         *ty  = CONS;
     136           0 :         *tag = UT_Set;
     137           0 :         break;
     138        1159 :     case TTag:
     139        1159 :         *cl  = t->tag.tagclass;
     140        1159 :         *ty  = is_primitive_type(t->subtype->type) ? PRIM : CONS;
     141        1159 :         *tag = t->tag.tagvalue;
     142        1159 :         break;
     143          57 :     case TType:
     144          57 :         if ((t->symbol->stype == Stype && t->symbol->type == NULL)
     145          57 :             || t->symbol->stype == SUndefined) {
     146           0 :             lex_error_message("%s is imported or still undefined, "
     147             :                               " can't generate tag checking data in CHOICE "
     148             :                               "without this information",
     149           0 :                               t->symbol->name);
     150           0 :             exit(1);
     151             :         }
     152          57 :         find_tag(t->symbol->type, cl, ty, tag);
     153          57 :         return;
     154           0 :     case TUTCTime:
     155           0 :         *cl  = ASN1_C_UNIV;
     156           0 :         *ty  = PRIM;
     157           0 :         *tag = UT_UTCTime;
     158           0 :         break;
     159           0 :     case TUTF8String:
     160           0 :         *cl  = ASN1_C_UNIV;
     161           0 :         *ty  = PRIM;
     162           0 :         *tag = UT_UTF8String;
     163           0 :         break;
     164           0 :     case TBMPString:
     165           0 :         *cl  = ASN1_C_UNIV;
     166           0 :         *ty  = PRIM;
     167           0 :         *tag = UT_BMPString;
     168           0 :         break;
     169           0 :     case TUniversalString:
     170           0 :         *cl  = ASN1_C_UNIV;
     171           0 :         *ty  = PRIM;
     172           0 :         *tag = UT_UniversalString;
     173           0 :         break;
     174           0 :     case TVisibleString:
     175           0 :         *cl  = ASN1_C_UNIV;
     176           0 :         *ty  = PRIM;
     177           0 :         *tag = UT_VisibleString;
     178           0 :         break;
     179           0 :     default:
     180           0 :         abort();
     181             :     }
     182             : }
     183             : 
     184             : static void
     185         152 : range_check(const char *name,
     186             :             const char *length,
     187             :             const char *forwstr,
     188             :             struct range *r)
     189             : {
     190         152 :     if (r->min == r->max + 2 || r->min < r->max)
     191           0 :         fprintf (codefile,
     192             :                  "if ((%s)->%s > %d) {\n"
     193             :                  "e = ASN1_MAX_CONSTRAINT; %s;\n"
     194             :                  "}\n",
     195             :                  name, length, r->max, forwstr);
     196         152 :     if (r->min - 1 == r->max || r->min < r->max)
     197         133 :         fprintf (codefile,
     198             :                  "if ((%s)->%s < %d) {\n"
     199             :                  "e = ASN1_MIN_CONSTRAINT; %s;\n"
     200             :                  "}\n",
     201             :                  name, length, r->min, forwstr);
     202         152 :     if (r->max == r->min)
     203          19 :         fprintf (codefile,
     204             :                  "if ((%s)->%s != %d) {\n"
     205             :                  "e = ASN1_EXACT_CONSTRAINT; %s;\n"
     206             :                  "}\n",
     207             :                  name, length, r->min, forwstr);
     208         152 : }
     209             : 
     210             : static int
     211       38684 : decode_type (const char *name, const Type *t, int optional,
     212             :              const char *forwstr, const char *tmpstr, const char *dertype,
     213             :              unsigned int depth)
     214             : {
     215       38684 :     switch (t->type) {
     216        8778 :     case TType: {
     217        8778 :         if (optional)
     218         133 :             fprintf(codefile,
     219             :                     "%s = calloc(1, sizeof(*%s));\n"
     220             :                     "if (%s == NULL) %s;\n",
     221             :                     name, name, name, forwstr);
     222        9240 :         fprintf (codefile,
     223             :                  "e = decode_%s(p, len, %s, &l);\n",
     224        8778 :                  t->symbol->gen_name, name);
     225        8778 :         if (optional) {
     226         133 :             fprintf (codefile,
     227             :                      "if(e) {\n"
     228             :                      "free(%s);\n"
     229             :                      "%s = NULL;\n"
     230             :                      "} else {\n"
     231             :                      "p += l; len -= l; ret += l;\n"
     232             :                      "}\n",
     233             :                      name, name);
     234             :         } else {
     235        9100 :             fprintf (codefile,
     236             :                      "if(e) %s;\n",
     237             :                      forwstr);
     238        8645 :             fprintf (codefile,
     239             :                      "p += l; len -= l; ret += l;\n");
     240             :         }
     241        8316 :         break;
     242             :     }
     243        1672 :     case TInteger:
     244        1672 :         if(t->members) {
     245         320 :             fprintf(codefile,
     246             :                     "{\n"
     247             :                     "int enumint;\n");
     248         304 :             decode_primitive ("integer", "&enumint", forwstr);
     249         304 :             fprintf(codefile,
     250             :                     "*%s = enumint;\n"
     251             :                     "}\n",
     252             :                     name);
     253        1368 :         } else if (t->range == NULL) {
     254         684 :             decode_primitive ("heim_integer", name, forwstr);
     255         646 :         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
     256         126 :             decode_primitive ("integer", name, forwstr);
     257         513 :         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
     258         486 :             decode_primitive ("unsigned", name, forwstr);
     259           0 :         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
     260           0 :             decode_primitive ("unsigned", name, forwstr);
     261             :         } else
     262           0 :             errx(1, "%s: unsupported range %d -> %d",
     263           0 :                  name, t->range->min, t->range->max);
     264        1584 :         break;
     265         152 :     case TBoolean:
     266         144 :       decode_primitive ("boolean", name, forwstr);
     267         144 :       break;
     268           0 :     case TEnumerated:
     269           0 :         decode_primitive ("enumerated", name, forwstr);
     270           0 :         break;
     271        1824 :     case TOctetString:
     272        1824 :         if (dertype) {
     273         160 :             fprintf(codefile,
     274             :                     "if (%s == CONS) {\n",
     275             :                     dertype);
     276         152 :             decode_primitive("octet_string_ber", name, forwstr);
     277         152 :             fprintf(codefile,
     278             :                     "} else {\n");
     279             :         }
     280        1824 :         decode_primitive ("octet_string", name, forwstr);
     281        1824 :         if (dertype)
     282         152 :             fprintf(codefile, "}\n");
     283        1824 :         if (t->range)
     284          19 :             range_check(name, "length", forwstr, t->range);
     285        1728 :         break;
     286         418 :     case TBitString: {
     287             :         Member *m;
     288         418 :         int pos = 0;
     289             : 
     290         418 :         if (ASN1_TAILQ_EMPTY(t->members)) {
     291         216 :             decode_primitive ("bit_string", name, forwstr);
     292         216 :             break;
     293             :         }
     294         200 :         fprintf(codefile,
     295             :                 "if (len < 1) return ASN1_OVERRUN;\n"
     296             :                 "p++; len--; ret++;\n");
     297         200 :         fprintf(codefile,
     298             :                 "do {\n"
     299             :                 "if (len < 1) break;\n");
     300        1919 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     301        3576 :             while (m->val / 8 > pos / 8) {
     302         220 :                 fprintf (codefile,
     303             :                          "p++; len--; ret++;\n"
     304             :                          "if (len < 1) break;\n");
     305         209 :                 pos += 8;
     306             :             }
     307        1820 :             fprintf (codefile,
     308             :                      "(%s)->%s = (*p >> %d) & 1;\n",
     309        1729 :                      name, m->gen_name, 7 - m->val % 8);
     310             :         }
     311         200 :         fprintf(codefile,
     312             :                 "} while(0);\n");
     313         190 :         fprintf (codefile,
     314             :                  "p += len; ret += len;\n");
     315         180 :         break;
     316             :     }
     317        3173 :     case TSequence: {
     318             :         Member *m;
     319             : 
     320        3173 :         if (t->members == NULL)
     321           0 :             break;
     322             : 
     323       15105 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     324       11932 :             char *s = NULL;
     325             : 
     326       11932 :             if (m->ellipsis)
     327         513 :                 continue;
     328             : 
     329       12020 :             if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
     330       11419 :                           name, m->gen_name) < 0 || s == NULL)
     331           0 :                 errx(1, "malloc");
     332       11419 :             decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL,
     333             :                 depth + 1);
     334       11419 :             free (s);
     335             :         }
     336             : 
     337        3006 :         break;
     338             :     }
     339           0 :     case TSet: {
     340             :         Member *m;
     341             :         unsigned int memno;
     342             : 
     343           0 :         if(t->members == NULL)
     344           0 :             break;
     345             : 
     346           0 :         fprintf(codefile, "{\n");
     347           0 :         fprintf(codefile, "unsigned int members = 0;\n");
     348           0 :         fprintf(codefile, "while(len > 0) {\n");
     349           0 :         fprintf(codefile,
     350             :                 "Der_class class;\n"
     351             :                 "Der_type type;\n"
     352             :                 "int tag;\n"
     353             :                 "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
     354             :                 "if(e) %s;\n", forwstr);
     355           0 :         fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
     356           0 :         memno = 0;
     357           0 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     358             :             char *s;
     359             : 
     360           0 :             assert(m->type->type == TTag);
     361             : 
     362           0 :             fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
     363           0 :                     classname(m->type->tag.tagclass),
     364           0 :                     is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS",
     365           0 :                     valuename(m->type->tag.tagclass, m->type->tag.tagvalue));
     366             : 
     367           0 :             if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
     368           0 :                 errx(1, "malloc");
     369           0 :             if(m->optional)
     370           0 :                 fprintf(codefile,
     371             :                         "%s = calloc(1, sizeof(*%s));\n"
     372             :                         "if (%s == NULL) { e = ENOMEM; %s; }\n",
     373             :                         s, s, s, forwstr);
     374           0 :             decode_type (s, m->type, 0, forwstr, m->gen_name, NULL, depth + 1);
     375           0 :             free (s);
     376             : 
     377           0 :             fprintf(codefile, "members |= (1 << %d);\n", memno);
     378           0 :             memno++;
     379           0 :             fprintf(codefile, "break;\n");
     380             :         }
     381           0 :         fprintf(codefile,
     382             :                 "default:\n"
     383             :                 "return ASN1_MISPLACED_FIELD;\n"
     384             :                 "break;\n");
     385           0 :         fprintf(codefile, "}\n");
     386           0 :         fprintf(codefile, "}\n");
     387           0 :         memno = 0;
     388           0 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     389             :             char *s;
     390             : 
     391           0 :             if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL)
     392           0 :                 errx(1, "malloc");
     393           0 :             fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno);
     394           0 :             if(m->optional)
     395           0 :                 fprintf(codefile, "%s = NULL;\n", s);
     396           0 :             else if(m->defval)
     397           0 :                 gen_assign_defval(s, m->defval);
     398             :             else
     399           0 :                 fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
     400           0 :             free(s);
     401           0 :             memno++;
     402             :         }
     403           0 :         fprintf(codefile, "}\n");
     404           0 :         break;
     405             :     }
     406        1368 :     case TSetOf:
     407             :     case TSequenceOf: {
     408        1368 :         char *n = NULL;
     409        1368 :         char *sname = NULL;
     410             : 
     411        1440 :         fprintf (codefile,
     412             :                  "{\n"
     413             :                  "size_t %s_origlen = len;\n"
     414             :                  "size_t %s_oldret = ret;\n"
     415             :                  "size_t %s_olen = 0;\n"
     416             :                  "void *%s_tmp;\n"
     417             :                  "ret = 0;\n"
     418             :                  "(%s)->len = 0;\n"
     419             :                  "(%s)->val = NULL;\n",
     420             :                  tmpstr,
     421             :                  tmpstr,
     422             :                  tmpstr,
     423             :                  tmpstr,
     424             :                  name,
     425             :                  name);
     426             : 
     427        1440 :         fprintf (codefile,
     428             :                  "while(ret < %s_origlen) {\n"
     429             :                  "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
     430             :                  "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
     431             :                  "%s_olen = %s_nlen;\n"
     432             :                  "%s_tmp = realloc((%s)->val, %s_olen);\n"
     433             :                  "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
     434             :                  "(%s)->val = %s_tmp;\n",
     435             :                  tmpstr,
     436             :                  tmpstr, tmpstr, name,
     437             :                  tmpstr, tmpstr, forwstr,
     438             :                  tmpstr, tmpstr,
     439             :                  tmpstr, name, tmpstr,
     440             :                  tmpstr, forwstr,
     441             :                  name, tmpstr);
     442             : 
     443        1368 :         if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL)
     444           0 :             errx(1, "malloc");
     445        1368 :         if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL)
     446           0 :             errx(1, "malloc");
     447        1368 :         decode_type (n, t->subtype, 0, forwstr, sname, NULL, depth + 1);
     448        1440 :         fprintf (codefile,
     449             :                  "(%s)->len++;\n"
     450             :                  "len = %s_origlen - ret;\n"
     451             :                  "}\n"
     452             :                  "ret += %s_oldret;\n"
     453             :                  "}\n",
     454             :                  name,
     455             :                  tmpstr, tmpstr);
     456        1368 :         if (t->range)
     457         133 :             range_check(name, "len", forwstr, t->range);
     458        1368 :         free (n);
     459        1368 :         free (sname);
     460        1296 :         break;
     461             :     }
     462         114 :     case TGeneralizedTime:
     463         108 :         decode_primitive ("generalized_time", name, forwstr);
     464         108 :         break;
     465         266 :     case TGeneralString:
     466         252 :         decode_primitive ("general_string", name, forwstr);
     467         252 :         break;
     468          19 :     case TTeletexString:
     469          18 :         decode_primitive ("general_string", name, forwstr);
     470          18 :         break;
     471       19152 :     case TTag:{
     472       19152 :         char *tname = NULL, *typestring = NULL;
     473       19152 :         char *ide = NULL;
     474             : 
     475       19152 :         if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL)
     476           0 :             errx(1, "malloc");
     477             : 
     478       20160 :         fprintf(codefile,
     479             :                 "{\n"
     480             :                 "size_t %s_datalen, %s_oldlen;\n"
     481             :                 "Der_type %s;\n",
     482             :                 tmpstr, tmpstr, typestring);
     483       19152 :         if(support_ber)
     484         779 :             fprintf(codefile,
     485             :                     "int is_indefinite%u;\n", depth);
     486             : 
     487       58464 :         fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
     488             :                 "&%s_datalen, &l);\n",
     489       19152 :                 classname(t->tag.tagclass),
     490             :                 typestring,
     491       19152 :                 valuename(t->tag.tagclass, t->tag.tagvalue),
     492             :                 tmpstr);
     493             : 
     494             :         /* XXX hardcode for now */
     495       19152 :         if (support_ber && t->subtype->type == TOctetString) {
     496         152 :             ide = typestring;
     497             :         } else {
     498       19000 :             fprintf(codefile,
     499             :                     "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
     500             :                     typestring,
     501       19000 :                     is_primitive_type(t->subtype->type) ? "PRIM" : "CONS");
     502             :         }
     503             : 
     504       19152 :         if(optional) {
     505        4256 :             fprintf(codefile,
     506             :                     "if(e) {\n"
     507             :                     "%s = NULL;\n"
     508             :                     "} else {\n"
     509             :                      "%s = calloc(1, sizeof(*%s));\n"
     510             :                      "if (%s == NULL) { e = ENOMEM; %s; }\n",
     511             :                      name, name, name, name, forwstr);
     512             :         } else {
     513       14896 :             fprintf(codefile, "if(e) %s;\n", forwstr);
     514             :         }
     515       20160 :         fprintf (codefile,
     516             :                  "p += l; len -= l; ret += l;\n"
     517             :                  "%s_oldlen = len;\n",
     518             :                  tmpstr);
     519       19152 :         if(support_ber)
     520         779 :             fprintf (codefile,
     521             :                      "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
     522             :                      "{ e = ASN1_BAD_FORMAT; %s; }\n"
     523             :                      "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }",
     524             :                      depth, tmpstr, forwstr, depth, forwstr);
     525             :         else
     526       18373 :             fprintf(codefile,
     527             :                     "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
     528             :                     "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
     529       19152 :         if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL)
     530           0 :             errx(1, "malloc");
     531       19152 :         decode_type (name, t->subtype, 0, forwstr, tname, ide, depth + 1);
     532       19152 :         if(support_ber)
     533         779 :             fprintf(codefile,
     534             :                     "if(is_indefinite%u){\n"
     535             :                     "len += 2;\n"
     536             :                     "e = der_match_tag_and_length(p, len, "
     537             :                     "(Der_class)0, &%s, UT_EndOfContent, "
     538             :                     "&%s_datalen, &l);\n"
     539             :                     "if(e) %s;\n"
     540             :                     "p += l; len -= l; ret += l;\n"
     541             :                     "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n"
     542             :                     "} else \n",
     543             :                     depth,
     544             :                     typestring,
     545             :                     tmpstr,
     546             :                     forwstr,
     547             :                     typestring, forwstr);
     548       20160 :         fprintf(codefile,
     549             :                 "len = %s_oldlen - %s_datalen;\n",
     550             :                 tmpstr, tmpstr);
     551       19152 :         if(optional)
     552        4256 :             fprintf(codefile,
     553             :                     "}\n");
     554       20160 :         fprintf(codefile,
     555             :                 "}\n");
     556       19152 :         free(tname);
     557       19152 :         free(typestring);
     558       18144 :         break;
     559             :     }
     560         380 :     case TChoice: {
     561         380 :         Member *m, *have_ellipsis = NULL;
     562         380 :         const char *els = "";
     563             : 
     564         380 :         if (t->members == NULL)
     565           0 :             break;
     566             : 
     567        1634 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     568        1254 :             const Type *tt = m->type;
     569        1254 :             char *s = NULL;
     570             :             Der_class cl;
     571             :             Der_type  ty;
     572             :             unsigned  tag;
     573             : 
     574        1254 :             if (m->ellipsis) {
     575          95 :                 have_ellipsis = m;
     576          95 :                 continue;
     577             :             }
     578             : 
     579        1159 :             find_tag(tt, &cl, &ty, &tag);
     580             : 
     581        2379 :             fprintf(codefile,
     582             :                     "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
     583             :                     els,
     584             :                     classname(cl),
     585        1159 :                     ty ? "CONS" : "PRIM",
     586             :                     valuename(cl, tag));
     587        1220 :             if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
     588        1159 :                           name, m->gen_name) < 0 || s == NULL)
     589           0 :                 errx(1, "malloc");
     590        1159 :             decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL,
     591             :                 depth + 1);
     592        1220 :             fprintf(codefile,
     593             :                     "(%s)->element = %s;\n",
     594             :                     name, m->label);
     595        1159 :             free(s);
     596        1220 :             fprintf(codefile,
     597             :                     "}\n");
     598        1159 :             els = "else ";
     599             :         }
     600         380 :         if (have_ellipsis) {
     601          95 :             fprintf(codefile,
     602             :                     "else {\n"
     603             :                     "(%s)->u.%s.data = calloc(1, len);\n"
     604             :                     "if ((%s)->u.%s.data == NULL) {\n"
     605             :                     "e = ENOMEM; %s;\n"
     606             :                     "}\n"
     607             :                     "(%s)->u.%s.length = len;\n"
     608             :                     "memcpy((%s)->u.%s.data, p, len);\n"
     609             :                     "(%s)->element = %s;\n"
     610             :                     "p += len;\n"
     611             :                     "ret += len;\n"
     612             :                     "len = 0;\n"
     613             :                     "}\n",
     614             :                     name, have_ellipsis->gen_name,
     615             :                     name, have_ellipsis->gen_name,
     616             :                     forwstr,
     617             :                     name, have_ellipsis->gen_name,
     618             :                     name, have_ellipsis->gen_name,
     619             :                     name, have_ellipsis->label);
     620             :         } else {
     621         285 :             fprintf(codefile,
     622             :                     "else {\n"
     623             :                     "e = ASN1_PARSE_ERROR;\n"
     624             :                     "%s;\n"
     625             :                     "}\n",
     626             :                     forwstr);
     627             :         }
     628         360 :         break;
     629             :     }
     630          19 :     case TUTCTime:
     631          18 :         decode_primitive ("utctime", name, forwstr);
     632          18 :         break;
     633         760 :     case TUTF8String:
     634         720 :         decode_primitive ("utf8string", name, forwstr);
     635         720 :         break;
     636          19 :     case TPrintableString:
     637          18 :         decode_primitive ("printable_string", name, forwstr);
     638          18 :         break;
     639          76 :     case TIA5String:
     640          72 :         decode_primitive ("ia5_string", name, forwstr);
     641          72 :         break;
     642          38 :     case TBMPString:
     643          36 :         decode_primitive ("bmp_string", name, forwstr);
     644          36 :         break;
     645          19 :     case TUniversalString:
     646          18 :         decode_primitive ("universal_string", name, forwstr);
     647          18 :         break;
     648          19 :     case TVisibleString:
     649          18 :         decode_primitive ("visible_string", name, forwstr);
     650          18 :         break;
     651          57 :     case TNull:
     652          57 :         fprintf (codefile, "/* NULL */\n");
     653          54 :         break;
     654         361 :     case TOID:
     655         342 :         decode_primitive ("oid", name, forwstr);
     656         342 :         break;
     657           0 :     default :
     658           0 :         abort ();
     659             :     }
     660       36648 :     return 0;
     661             : }
     662             : 
     663             : void
     664        5586 : generate_type_decode (const Symbol *s)
     665             : {
     666        5586 :     int preserve = preserve_type(s->name) ? TRUE : FALSE;
     667             : 
     668        5880 :     fprintf (codefile, "int ASN1CALL\n"
     669             :              "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE,"
     670             :              " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n"
     671             :              "{\n",
     672             :              s->gen_name, s->gen_name);
     673             : 
     674        5586 :     switch (s->type->type) {
     675        5586 :     case TInteger:
     676             :     case TBoolean:
     677             :     case TOctetString:
     678             :     case TOID:
     679             :     case TGeneralizedTime:
     680             :     case TGeneralString:
     681             :     case TTeletexString:
     682             :     case TUTF8String:
     683             :     case TPrintableString:
     684             :     case TIA5String:
     685             :     case TBMPString:
     686             :     case TUniversalString:
     687             :     case TVisibleString:
     688             :     case TUTCTime:
     689             :     case TNull:
     690             :     case TEnumerated:
     691             :     case TBitString:
     692             :     case TSequence:
     693             :     case TSequenceOf:
     694             :     case TSet:
     695             :     case TSetOf:
     696             :     case TTag:
     697             :     case TType:
     698             :     case TChoice:
     699        5880 :         fprintf (codefile,
     700             :                  "size_t ret = 0;\n"
     701             :                  "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
     702             :                  "int e HEIMDAL_UNUSED_ATTRIBUTE;\n");
     703        5586 :         if (preserve)
     704         114 :             fprintf (codefile, "const unsigned char *begin = p;\n");
     705             : 
     706        5880 :         fprintf (codefile, "\n");
     707        5880 :         fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
     708             : 
     709        5586 :         decode_type ("data", s->type, 0, "goto fail", "Top", NULL, 1);
     710        5586 :         if (preserve)
     711         114 :             fprintf (codefile,
     712             :                      "data->_save.data = calloc(1, ret);\n"
     713             :                      "if (data->_save.data == NULL) { \n"
     714             :                      "e = ENOMEM; goto fail; \n"
     715             :                      "}\n"
     716             :                      "data->_save.length = ret;\n"
     717             :                      "memcpy(data->_save.data, begin, ret);\n");
     718        5880 :         fprintf (codefile,
     719             :                  "if(size) *size = ret;\n"
     720             :                  "return 0;\n");
     721        5880 :         fprintf (codefile,
     722             :                  "fail:\n"
     723             :                  "free_%s(data);\n"
     724             :                  "return e;\n",
     725             :                  s->gen_name);
     726        5292 :         break;
     727           0 :     default:
     728           0 :         abort ();
     729             :     }
     730        5880 :     fprintf (codefile, "}\n\n");
     731        5586 : }

Generated by: LCOV version 1.13