LTP GCOV extension - code coverage report
Current view: directory - lib/asn1 - gen_decode.c
Test: samba_4_0_test.lcov.info
Date: 2010-08-06 Instrumented lines: 312
Code covered: 57.1 % Executed lines: 178

       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                 : decode_primitive (const char *typename, const char *name, const char *forwstr)
      41             296 : {
      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             296 :     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             296 : }
      58                 : 
      59                 : static void
      60                 : find_tag (const Type *t,
      61                 :           Der_class *cl, Der_type *ty, unsigned *tag)
      62              60 : {
      63              60 :     switch (t->type) {
      64                 :     case TBitString:
      65               0 :         *cl  = ASN1_C_UNIV;
      66               0 :         *ty  = PRIM;
      67               0 :         *tag = UT_BitString;
      68               0 :         break;
      69                 :     case TBoolean:
      70               0 :         *cl  = ASN1_C_UNIV;
      71               0 :         *ty  = PRIM;
      72               0 :         *tag = UT_Boolean;
      73               0 :         break;
      74                 :     case TChoice:
      75               0 :         errx(1, "Cannot have recursive CHOICE");
      76                 :     case TEnumerated:
      77               0 :         *cl  = ASN1_C_UNIV;
      78               0 :         *ty  = PRIM;
      79               0 :         *tag = UT_Enumerated;
      80               0 :         break;
      81                 :     case TGeneralString:
      82               0 :         *cl  = ASN1_C_UNIV;
      83               0 :         *ty  = PRIM;
      84               0 :         *tag = UT_GeneralString;
      85               0 :         break;
      86                 :     case TTeletexString:
      87               0 :         *cl  = ASN1_C_UNIV;
      88               0 :         *ty  = PRIM;
      89               0 :         *tag = UT_TeletexString;
      90               0 :         break;
      91                 :     case TGeneralizedTime:
      92               0 :         *cl  = ASN1_C_UNIV;
      93               0 :         *ty  = PRIM;
      94               0 :         *tag = UT_GeneralizedTime;
      95               0 :         break;
      96                 :     case TIA5String:
      97               0 :         *cl  = ASN1_C_UNIV;
      98               0 :         *ty  = PRIM;
      99               0 :         *tag = UT_IA5String;
     100               0 :         break;
     101                 :     case TInteger:
     102               0 :         *cl  = ASN1_C_UNIV;
     103               0 :         *ty  = PRIM;
     104               0 :         *tag = UT_Integer;
     105               0 :         break;
     106                 :     case TNull:
     107               0 :         *cl  = ASN1_C_UNIV;
     108               0 :         *ty  = PRIM;
     109               0 :         *tag = UT_Null;
     110               0 :         break;
     111                 :     case TOID:
     112               0 :         *cl  = ASN1_C_UNIV;
     113               0 :         *ty  = PRIM;
     114               0 :         *tag = UT_OID;
     115               0 :         break;
     116                 :     case TOctetString:
     117               0 :         *cl  = ASN1_C_UNIV;
     118               0 :         *ty  = PRIM;
     119               0 :         *tag = UT_OctetString;
     120               0 :         break;
     121                 :     case TPrintableString:
     122               0 :         *cl  = ASN1_C_UNIV;
     123               0 :         *ty  = PRIM;
     124               0 :         *tag = UT_PrintableString;
     125               0 :         break;
     126                 :     case TSequence:
     127                 :     case TSequenceOf:
     128               0 :         *cl  = ASN1_C_UNIV;
     129               0 :         *ty  = CONS;
     130               0 :         *tag = UT_Sequence;
     131               0 :         break;
     132                 :     case TSet:
     133                 :     case TSetOf:
     134               0 :         *cl  = ASN1_C_UNIV;
     135               0 :         *ty  = CONS;
     136               0 :         *tag = UT_Set;
     137               0 :         break;
     138                 :     case TTag:
     139              57 :         *cl  = t->tag.tagclass;
     140              57 :         *ty  = is_primitive_type(t->subtype->type) ? PRIM : CONS;
     141              57 :         *tag = t->tag.tagvalue;
     142              57 :         break;
     143                 :     case TType:
     144               3 :         if ((t->symbol->stype == Stype && t->symbol->type == NULL)
     145                 :             || t->symbol->stype == SUndefined) {
     146               0 :             error_message("%s is imported or still undefined, "
     147                 :                           " can't generate tag checking data in CHOICE "
     148                 :                           "without this information",
     149                 :                           t->symbol->name);
     150               0 :             exit(1);
     151                 :         }
     152               3 :         find_tag(t->symbol->type, cl, ty, tag);
     153               3 :         return;
     154                 :     case TUTCTime:
     155               0 :         *cl  = ASN1_C_UNIV;
     156               0 :         *ty  = PRIM;
     157               0 :         *tag = UT_UTCTime;
     158               0 :         break;
     159                 :     case TUTF8String:
     160               0 :         *cl  = ASN1_C_UNIV;
     161               0 :         *ty  = PRIM;
     162               0 :         *tag = UT_UTF8String;
     163               0 :         break;
     164                 :     case TBMPString:
     165               0 :         *cl  = ASN1_C_UNIV;
     166               0 :         *ty  = PRIM;
     167               0 :         *tag = UT_BMPString;
     168               0 :         break;
     169                 :     case TUniversalString:
     170               0 :         *cl  = ASN1_C_UNIV;
     171               0 :         *ty  = PRIM;
     172               0 :         *tag = UT_UniversalString;
     173               0 :         break;
     174                 :     case TVisibleString:
     175               0 :         *cl  = ASN1_C_UNIV;
     176               0 :         *ty  = PRIM;
     177               0 :         *tag = UT_VisibleString;
     178               0 :         break;
     179                 :     default:
     180               0 :         abort();
     181                 :     }
     182                 : }
     183                 : 
     184                 : static void
     185                 : range_check(const char *name,
     186                 :             const char *length,
     187                 :             const char *forwstr,
     188                 :             struct range *r)
     189               8 : {
     190               8 :     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               8 :     if (r->min - 1 == r->max || r->min < r->max)
     197               7 :         fprintf (codefile,
     198                 :                  "if ((%s)->%s < %d) {\n"
     199                 :                  "e = ASN1_MIN_CONSTRAINT; %s;\n"
     200                 :                  "}\n",
     201                 :                  name, length, r->min, forwstr);
     202               8 :     if (r->max == r->min)
     203               1 :         fprintf (codefile,
     204                 :                  "if ((%s)->%s != %d) {\n"
     205                 :                  "e = ASN1_EXACT_CONSTRAINT; %s;\n"
     206                 :                  "}\n",
     207                 :                  name, length, r->min, forwstr);
     208               8 : }
     209                 : 
     210                 : static int
     211                 : decode_type (const char *name, const Type *t, int optional,
     212                 :              const char *forwstr, const char *tmpstr, const char *dertype)
     213            2025 : {
     214            2025 :     switch (t->type) {
     215                 :     case TType: {
     216             462 :         if (optional)
     217               7 :             fprintf(codefile,
     218                 :                     "%s = calloc(1, sizeof(*%s));\n"
     219                 :                     "if (%s == NULL) %s;\n",
     220                 :                     name, name, name, forwstr);
     221             462 :         fprintf (codefile,
     222                 :                  "e = decode_%s(p, len, %s, &l);\n",
     223                 :                  t->symbol->gen_name, name);
     224             462 :         if (optional) {
     225               7 :             fprintf (codefile,
     226                 :                      "if(e) {\n"
     227                 :                      "free(%s);\n"
     228                 :                      "%s = NULL;\n"
     229                 :                      "} else {\n"
     230                 :                      "p += l; len -= l; ret += l;\n"
     231                 :                      "}\n",
     232                 :                      name, name);
     233                 :         } else {
     234             455 :             fprintf (codefile,
     235                 :                      "if(e) %s;\n",
     236                 :                      forwstr);
     237             455 :             fprintf (codefile,
     238                 :                      "p += l; len -= l; ret += l;\n");
     239                 :         }
     240             462 :         break;
     241                 :     }
     242                 :     case TInteger:
     243              83 :         if(t->members) {
     244              16 :             fprintf(codefile,
     245                 :                     "{\n"
     246                 :                     "int enumint;\n");
     247              16 :             decode_primitive ("integer", "&enumint", forwstr);
     248              16 :             fprintf(codefile,
     249                 :                     "*%s = enumint;\n"
     250                 :                     "}\n",
     251                 :                     name);
     252              67 :         } else if (t->range == NULL) {
     253              35 :             decode_primitive ("heim_integer", name, forwstr);
     254              39 :         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
     255               7 :             decode_primitive ("integer", name, forwstr);
     256              50 :         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
     257              25 :             decode_primitive ("unsigned", name, forwstr);
     258               0 :         } else if (t->range->min == 0 && t->range->max == INT_MAX) {
     259               0 :             decode_primitive ("unsigned", name, forwstr);
     260                 :         } else
     261               0 :             errx(1, "%s: unsupported range %d -> %d",
     262                 :                  name, t->range->min, t->range->max);
     263              83 :         break;
     264                 :     case TBoolean:
     265               8 :       decode_primitive ("boolean", name, forwstr);
     266               8 :       break;
     267                 :     case TEnumerated:
     268               0 :         decode_primitive ("enumerated", name, forwstr);
     269               0 :         break;
     270                 :     case TOctetString:
     271              96 :         if (dertype) {
     272               8 :             fprintf(codefile,
     273                 :                     "if (%s == CONS) {\n",
     274                 :                     dertype);
     275               8 :             decode_primitive("octet_string_ber", name, forwstr);
     276               8 :             fprintf(codefile,
     277                 :                     "} else {\n");
     278                 :         }
     279              96 :         decode_primitive ("octet_string", name, forwstr);
     280              96 :         if (dertype)
     281               8 :             fprintf(codefile, "}\n");
     282              96 :         if (t->range)
     283               1 :             range_check(name, "length", forwstr, t->range);
     284              96 :         break;
     285                 :     case TBitString: {
     286                 :         Member *m;
     287              22 :         int pos = 0;
     288                 : 
     289              22 :         if (ASN1_TAILQ_EMPTY(t->members)) {
     290              12 :             decode_primitive ("bit_string", name, forwstr);
     291              12 :             break;
     292                 :         }
     293              10 :         fprintf(codefile,
     294                 :                 "if (len < 1) return ASN1_OVERRUN;\n"
     295                 :                 "p++; len--; ret++;\n");
     296              10 :         fprintf(codefile,
     297                 :                 "do {\n"
     298                 :                 "if (len < 1) break;\n");
     299              99 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     300             188 :             while (m->val / 8 > pos / 8) {
     301              10 :                 fprintf (codefile,
     302                 :                          "p++; len--; ret++;\n"
     303                 :                          "if (len < 1) break;\n");
     304              10 :                 pos += 8;
     305                 :             }
     306              89 :             fprintf (codefile,
     307                 :                      "(%s)->%s = (*p >> %d) & 1;\n",
     308                 :                      name, m->gen_name, 7 - m->val % 8);
     309                 :         }
     310              10 :         fprintf(codefile,
     311                 :                 "} while(0);\n");
     312              10 :         fprintf (codefile,
     313                 :                  "p += len; ret += len;\n");
     314              10 :         break;
     315                 :     }
     316                 :     case TSequence: {
     317                 :         Member *m;
     318                 : 
     319             168 :         if (t->members == NULL)
     320               0 :             break;
     321                 : 
     322             795 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     323                 :             char *s;
     324                 : 
     325             627 :             if (m->ellipsis)
     326              26 :                 continue;
     327                 : 
     328             601 :             asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
     329                 :                       name, m->gen_name);
     330             601 :             if (s == NULL)
     331               0 :                 errx(1, "malloc");
     332             601 :             decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL);
     333             601 :             free (s);
     334                 :         }
     335                 : 
     336             168 :         break;
     337                 :     }
     338                 :     case TSet: {
     339                 :         Member *m;
     340                 :         unsigned int memno;
     341                 : 
     342               0 :         if(t->members == NULL)
     343               0 :             break;
     344                 : 
     345               0 :         fprintf(codefile, "{\n");
     346               0 :         fprintf(codefile, "unsigned int members = 0;\n");
     347               0 :         fprintf(codefile, "while(len > 0) {\n");
     348               0 :         fprintf(codefile,
     349                 :                 "Der_class class;\n"
     350                 :                 "Der_type type;\n"
     351                 :                 "int tag;\n"
     352                 :                 "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
     353                 :                 "if(e) %s;\n", forwstr);
     354               0 :         fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
     355               0 :         memno = 0;
     356               0 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     357                 :             char *s;
     358                 : 
     359               0 :             assert(m->type->type == TTag);
     360                 : 
     361               0 :             fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
     362                 :                     classname(m->type->tag.tagclass),
     363                 :                     is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS",
     364                 :                     valuename(m->type->tag.tagclass, m->type->tag.tagvalue));
     365                 : 
     366               0 :             asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
     367               0 :             if (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);
     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 :             asprintf (&s, "%s->%s", name, m->gen_name);
     392               0 :             if (s == NULL)
     393               0 :                 errx(1, "malloc");
     394               0 :             fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno);
     395               0 :             if(m->optional)
     396               0 :                 fprintf(codefile, "%s = NULL;\n", s);
     397               0 :             else if(m->defval)
     398               0 :                 gen_assign_defval(s, m->defval);
     399                 :             else
     400               0 :                 fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
     401               0 :             free(s);
     402               0 :             memno++;
     403                 :         }
     404               0 :         fprintf(codefile, "}\n");
     405               0 :         break;
     406                 :     }
     407                 :     case TSetOf:
     408                 :     case TSequenceOf: {
     409                 :         char *n;
     410                 :         char *sname;
     411                 : 
     412              72 :         fprintf (codefile,
     413                 :                  "{\n"
     414                 :                  "size_t %s_origlen = len;\n"
     415                 :                  "size_t %s_oldret = ret;\n"
     416                 :                  "size_t %s_olen = 0;\n"
     417                 :                  "void *%s_tmp;\n"
     418                 :                  "ret = 0;\n"
     419                 :                  "(%s)->len = 0;\n"
     420                 :                  "(%s)->val = NULL;\n",
     421                 :                  tmpstr,
     422                 :                  tmpstr,
     423                 :                  tmpstr,
     424                 :                  tmpstr,
     425                 :                  name,
     426                 :                  name);
     427                 : 
     428              72 :         fprintf (codefile,
     429                 :                  "while(ret < %s_origlen) {\n"
     430                 :                  "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
     431                 :                  "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
     432                 :                  "%s_olen = %s_nlen;\n"
     433                 :                  "%s_tmp = realloc((%s)->val, %s_olen);\n"
     434                 :                  "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
     435                 :                  "(%s)->val = %s_tmp;\n",
     436                 :                  tmpstr,
     437                 :                  tmpstr, tmpstr, name,
     438                 :                  tmpstr, tmpstr, forwstr,
     439                 :                  tmpstr, tmpstr,
     440                 :                  tmpstr, name, tmpstr,
     441                 :                  tmpstr, forwstr,
     442                 :                  name, tmpstr);
     443                 : 
     444              72 :         asprintf (&n, "&(%s)->val[(%s)->len]", name, name);
     445              72 :         if (n == NULL)
     446               0 :             errx(1, "malloc");
     447              72 :         asprintf (&sname, "%s_s_of", tmpstr);
     448              72 :         if (sname == NULL)
     449               0 :             errx(1, "malloc");
     450              72 :         decode_type (n, t->subtype, 0, forwstr, sname, NULL);
     451              72 :         fprintf (codefile,
     452                 :                  "(%s)->len++;\n"
     453                 :                  "len = %s_origlen - ret;\n"
     454                 :                  "}\n"
     455                 :                  "ret += %s_oldret;\n"
     456                 :                  "}\n",
     457                 :                  name,
     458                 :                  tmpstr, tmpstr);
     459              72 :         if (t->range)
     460               7 :             range_check(name, "len", forwstr, t->range);
     461              72 :         free (n);
     462              72 :         free (sname);
     463              72 :         break;
     464                 :     }
     465                 :     case TGeneralizedTime:
     466               6 :         decode_primitive ("generalized_time", name, forwstr);
     467               6 :         break;
     468                 :     case TGeneralString:
     469              14 :         decode_primitive ("general_string", name, forwstr);
     470              14 :         break;
     471                 :     case TTeletexString:
     472               1 :         decode_primitive ("general_string", name, forwstr);
     473               1 :         break;
     474                 :     case TTag:{
     475                 :         char *tname, *typestring;
     476            1002 :         char *ide = NULL;
     477                 : 
     478            1002 :         asprintf(&typestring, "%s_type", tmpstr);
     479                 : 
     480            1002 :         fprintf(codefile,
     481                 :                 "{\n"
     482                 :                 "size_t %s_datalen, %s_oldlen;\n"
     483                 :                 "Der_type %s;\n",
     484                 :                 tmpstr, tmpstr, typestring);
     485            1002 :         if(support_ber)
     486              41 :             fprintf(codefile,
     487                 :                     "int is_indefinite;\n");
     488                 : 
     489            1002 :         fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
     490                 :                 "&%s_datalen, &l);\n",
     491                 :                 classname(t->tag.tagclass),
     492                 :                 typestring,
     493                 :                 valuename(t->tag.tagclass, t->tag.tagvalue),
     494                 :                 tmpstr);
     495                 : 
     496                 :         /* XXX hardcode for now */
     497            1010 :         if (support_ber && t->subtype->type == TOctetString) {
     498               8 :             ide = typestring;
     499                 :         } else {
     500             994 :             fprintf(codefile,
     501                 :                     "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
     502                 :                     typestring,
     503                 :                     is_primitive_type(t->subtype->type) ? "PRIM" : "CONS");
     504                 :         }
     505                 : 
     506            1002 :         if(optional) {
     507             221 :             fprintf(codefile,
     508                 :                     "if(e) {\n"
     509                 :                     "%s = NULL;\n"
     510                 :                     "} else {\n"
     511                 :                      "%s = calloc(1, sizeof(*%s));\n"
     512                 :                      "if (%s == NULL) { e = ENOMEM; %s; }\n",
     513                 :                      name, name, name, name, forwstr);
     514                 :         } else {
     515             781 :             fprintf(codefile, "if(e) %s;\n", forwstr);
     516                 :         }
     517            1002 :         fprintf (codefile,
     518                 :                  "p += l; len -= l; ret += l;\n"
     519                 :                  "%s_oldlen = len;\n",
     520                 :                  tmpstr);
     521            1002 :         if(support_ber)
     522              41 :             fprintf (codefile,
     523                 :                      "if((is_indefinite = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
     524                 :                      "{ e = ASN1_BAD_FORMAT; %s; }\n"
     525                 :                      "if (is_indefinite) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }",
     526                 :                      tmpstr, forwstr, forwstr);
     527                 :         else
     528             961 :             fprintf(codefile,
     529                 :                     "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
     530                 :                     "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
     531            1002 :         asprintf (&tname, "%s_Tag", tmpstr);
     532            1002 :         if (tname == NULL)
     533               0 :             errx(1, "malloc");
     534            1002 :         decode_type (name, t->subtype, 0, forwstr, tname, ide);
     535            1002 :         if(support_ber)
     536              41 :             fprintf(codefile,
     537                 :                     "if(is_indefinite){\n"
     538                 :                     "len += 2;\n"
     539                 :                     "e = der_match_tag_and_length(p, len, "
     540                 :                     "(Der_class)0, &%s, UT_EndOfContent, "
     541                 :                     "&%s_datalen, &l);\n"
     542                 :                     "if(e) %s;\n"
     543                 :                     "p += l; len -= l; ret += l;\n"
     544                 :                     "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n"
     545                 :                     "} else \n",
     546                 :                     typestring,
     547                 :                     tmpstr,
     548                 :                     forwstr,
     549                 :                     typestring, forwstr);
     550            1002 :         fprintf(codefile,
     551                 :                 "len = %s_oldlen - %s_datalen;\n",
     552                 :                 tmpstr, tmpstr);
     553            1002 :         if(optional)
     554             221 :             fprintf(codefile,
     555                 :                     "}\n");
     556            1002 :         fprintf(codefile,
     557                 :                 "}\n");
     558            1002 :         free(tname);
     559            1002 :         free(typestring);
     560            1002 :         break;
     561                 :     }
     562                 :     case TChoice: {
     563              20 :         Member *m, *have_ellipsis = NULL;
     564              20 :         const char *els = "";
     565                 : 
     566              20 :         if (t->members == NULL)
     567               0 :             break;
     568                 : 
     569              82 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     570              62 :             const Type *tt = m->type;
     571                 :             char *s;
     572                 :             Der_class cl;
     573                 :             Der_type  ty;
     574                 :             unsigned  tag;
     575                 : 
     576              62 :             if (m->ellipsis) {
     577               5 :                 have_ellipsis = m;
     578               5 :                 continue;
     579                 :             }
     580                 : 
     581              57 :             find_tag(tt, &cl, &ty, &tag);
     582                 : 
     583              57 :             fprintf(codefile,
     584                 :                     "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
     585                 :                     els,
     586                 :                     classname(cl),
     587                 :                     ty ? "CONS" : "PRIM",
     588                 :                     valuename(cl, tag));
     589              57 :             asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
     590                 :                       name, m->gen_name);
     591              57 :             if (s == NULL)
     592               0 :                 errx(1, "malloc");
     593              57 :             decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL);
     594              57 :             fprintf(codefile,
     595                 :                     "(%s)->element = %s;\n",
     596                 :                     name, m->label);
     597              57 :             free(s);
     598              57 :             fprintf(codefile,
     599                 :                     "}\n");
     600              57 :             els = "else ";
     601                 :         }
     602              20 :         if (have_ellipsis) {
     603               5 :             fprintf(codefile,
     604                 :                     "else {\n"
     605                 :                     "(%s)->u.%s.data = calloc(1, len);\n"
     606                 :                     "if ((%s)->u.%s.data == NULL) {\n"
     607                 :                     "e = ENOMEM; %s;\n"
     608                 :                     "}\n"
     609                 :                     "(%s)->u.%s.length = len;\n"
     610                 :                     "memcpy((%s)->u.%s.data, p, len);\n"
     611                 :                     "(%s)->element = %s;\n"
     612                 :                     "p += len;\n"
     613                 :                     "ret += len;\n"
     614                 :                     "len -= len;\n"
     615                 :                     "}\n",
     616                 :                     name, have_ellipsis->gen_name,
     617                 :                     name, have_ellipsis->gen_name,
     618                 :                     forwstr,
     619                 :                     name, have_ellipsis->gen_name,
     620                 :                     name, have_ellipsis->gen_name,
     621                 :                     name, have_ellipsis->label);
     622                 :         } else {
     623              15 :             fprintf(codefile,
     624                 :                     "else {\n"
     625                 :                     "e = ASN1_PARSE_ERROR;\n"
     626                 :                     "%s;\n"
     627                 :                     "}\n",
     628                 :                     forwstr);
     629                 :         }
     630              20 :         break;
     631                 :     }
     632                 :     case TUTCTime:
     633               1 :         decode_primitive ("utctime", name, forwstr);
     634               1 :         break;
     635                 :     case TUTF8String:
     636              39 :         decode_primitive ("utf8string", name, forwstr);
     637              39 :         break;
     638                 :     case TPrintableString:
     639               1 :         decode_primitive ("printable_string", name, forwstr);
     640               1 :         break;
     641                 :     case TIA5String:
     642               4 :         decode_primitive ("ia5_string", name, forwstr);
     643               4 :         break;
     644                 :     case TBMPString:
     645               2 :         decode_primitive ("bmp_string", name, forwstr);
     646               2 :         break;
     647                 :     case TUniversalString:
     648               1 :         decode_primitive ("universal_string", name, forwstr);
     649               1 :         break;
     650                 :     case TVisibleString:
     651               1 :         decode_primitive ("visible_string", name, forwstr);
     652               1 :         break;
     653                 :     case TNull:
     654               3 :         fprintf (codefile, "/* NULL */\n");
     655               3 :         break;
     656                 :     case TOID:
     657              19 :         decode_primitive ("oid", name, forwstr);
     658              19 :         break;
     659                 :     default :
     660               0 :         abort ();
     661                 :     }
     662            2025 :     return 0;
     663                 : }
     664                 : 
     665                 : void
     666                 : generate_type_decode (const Symbol *s)
     667             293 : {
     668             293 :     int preserve = preserve_type(s->name) ? TRUE : FALSE;
     669                 : 
     670             293 :     fprintf (codefile, "int\n"
     671                 :              "decode_%s(const unsigned char *p,"
     672                 :              " size_t len, %s *data, size_t *size)\n"
     673                 :              "{\n",
     674                 :              s->gen_name, s->gen_name);
     675                 : 
     676             293 :     switch (s->type->type) {
     677                 :     case TInteger:
     678                 :     case TBoolean:
     679                 :     case TOctetString:
     680                 :     case TOID:
     681                 :     case TGeneralizedTime:
     682                 :     case TGeneralString:
     683                 :     case TTeletexString:
     684                 :     case TUTF8String:
     685                 :     case TPrintableString:
     686                 :     case TIA5String:
     687                 :     case TBMPString:
     688                 :     case TUniversalString:
     689                 :     case TVisibleString:
     690                 :     case TUTCTime:
     691                 :     case TNull:
     692                 :     case TEnumerated:
     693                 :     case TBitString:
     694                 :     case TSequence:
     695                 :     case TSequenceOf:
     696                 :     case TSet:
     697                 :     case TSetOf:
     698                 :     case TTag:
     699                 :     case TType:
     700                 :     case TChoice:
     701             293 :         fprintf (codefile,
     702                 :                  "size_t ret = 0;\n"
     703                 :                  "size_t l;\n"
     704                 :                  "int e;\n");
     705             293 :         if (preserve)
     706               6 :             fprintf (codefile, "const unsigned char *begin = p;\n");
     707                 : 
     708             293 :         fprintf (codefile, "\n");
     709             293 :         fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
     710                 : 
     711             293 :         decode_type ("data", s->type, 0, "goto fail", "Top", NULL);
     712             293 :         if (preserve)
     713               6 :             fprintf (codefile,
     714                 :                      "data->_save.data = calloc(1, ret);\n"
     715                 :                      "if (data->_save.data == NULL) { \n"
     716                 :                      "e = ENOMEM; goto fail; \n"
     717                 :                      "}\n"
     718                 :                      "data->_save.length = ret;\n"
     719                 :                      "memcpy(data->_save.data, begin, ret);\n");
     720             293 :         fprintf (codefile,
     721                 :                  "if(size) *size = ret;\n"
     722                 :                  "return 0;\n");
     723             293 :         fprintf (codefile,
     724                 :                  "fail:\n"
     725                 :                  "free_%s(data);\n"
     726                 :                  "return e;\n",
     727                 :                  s->gen_name);
     728                 :         break;
     729                 :     default:
     730               0 :         abort ();
     731                 :     }
     732             293 :     fprintf (codefile, "}\n\n");
     733             293 : }

Generated by: LTP GCOV extension version 1.6