LCOV - code coverage report
Current view: top level - lib/asn1 - gen_decode.c (source / functions) Hit Total Coverage
Test: samba_4_0_test.lcov.info Lines: 187 325 57.5 %
Date: 2014-04-02 Functions: 5 5 100.0 %
Branches: 110 189 58.2 %

           Branch data     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                 :        302 : 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                 :        302 :     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                 :        302 : }
      58                 :            : 
      59                 :            : static void
      60                 :         64 : find_tag (const Type *t,
      61                 :            :           Der_class *cl, Der_type *ty, unsigned *tag)
      62                 :            : {
      63   [ -  -  -  -  :         64 :     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                 :         61 :         *cl  = t->tag.tagclass;
     140                 :         61 :         *ty  = is_primitive_type(t->subtype->type) ? PRIM : CONS;
     141                 :         61 :         *tag = t->tag.tagvalue;
     142                 :         61 :         break;
     143                 :            :     case TType:
     144 [ +  - ][ +  - ]:          3 :         if ((t->symbol->stype == Stype && t->symbol->type == NULL)
                 [ -  + ]
     145                 :          3 :             || 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                 :          3 :         find_tag(t->symbol->type, cl, ty, tag);
     153                 :         64 :         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                 :          8 : range_check(const char *name,
     186                 :            :             const char *length,
     187                 :            :             const char *forwstr,
     188                 :            :             struct range *r)
     189                 :            : {
     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                 :       2048 : 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   [ +  +  +  -  :       2048 :     switch (t->type) {
          +  +  +  -  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  +  
                      - ]
     216                 :            :     case TType: {
     217         [ +  + ]:        466 :         if (optional)
     218                 :          7 :             fprintf(codefile,
     219                 :            :                     "%s = calloc(1, sizeof(*%s));\n"
     220                 :            :                     "if (%s == NULL) %s;\n",
     221                 :            :                     name, name, name, forwstr);
     222                 :        466 :         fprintf (codefile,
     223                 :            :                  "e = decode_%s(p, len, %s, &l);\n",
     224                 :        466 :                  t->symbol->gen_name, name);
     225         [ +  + ]:        466 :         if (optional) {
     226                 :          7 :             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                 :        459 :             fprintf (codefile,
     236                 :            :                      "if(e) %s;\n",
     237                 :            :                      forwstr);
     238                 :        459 :             fprintf (codefile,
     239                 :            :                      "p += l; len -= l; ret += l;\n");
     240                 :            :         }
     241                 :        466 :         break;
     242                 :            :     }
     243                 :            :     case TInteger:
     244         [ +  + ]:         88 :         if(t->members) {
     245                 :         16 :             fprintf(codefile,
     246                 :            :                     "{\n"
     247                 :            :                     "int enumint;\n");
     248                 :         16 :             decode_primitive ("integer", "&enumint", forwstr);
     249                 :         16 :             fprintf(codefile,
     250                 :            :                     "*%s = enumint;\n"
     251                 :            :                     "}\n",
     252                 :            :                     name);
     253         [ +  + ]:         72 :         } else if (t->range == NULL) {
     254                 :         38 :             decode_primitive ("heim_integer", name, forwstr);
     255 [ +  + ][ +  - ]:         41 :         } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
     256                 :          7 :             decode_primitive ("integer", name, forwstr);
     257 [ +  - ][ +  - ]:         54 :         } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
     258                 :         27 :             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                 :         88 :         break;
     265                 :            :     case TBoolean:
     266                 :          8 :       decode_primitive ("boolean", name, forwstr);
     267                 :          8 :       break;
     268                 :            :     case TEnumerated:
     269                 :          0 :         decode_primitive ("enumerated", name, forwstr);
     270                 :          0 :         break;
     271                 :            :     case TOctetString:
     272         [ +  + ]:         96 :         if (dertype) {
     273                 :          8 :             fprintf(codefile,
     274                 :            :                     "if (%s == CONS) {\n",
     275                 :            :                     dertype);
     276                 :          8 :             decode_primitive("octet_string_ber", name, forwstr);
     277                 :          8 :             fprintf(codefile,
     278                 :            :                     "} else {\n");
     279                 :            :         }
     280                 :         96 :         decode_primitive ("octet_string", name, forwstr);
     281         [ +  + ]:         96 :         if (dertype)
     282                 :          8 :             fprintf(codefile, "}\n");
     283         [ +  + ]:         96 :         if (t->range)
     284                 :          1 :             range_check(name, "length", forwstr, t->range);
     285                 :         96 :         break;
     286                 :            :     case TBitString: {
     287                 :            :         Member *m;
     288                 :         22 :         int pos = 0;
     289                 :            : 
     290         [ +  + ]:         22 :         if (ASN1_TAILQ_EMPTY(t->members)) {
     291                 :         12 :             decode_primitive ("bit_string", name, forwstr);
     292                 :         12 :             break;
     293                 :            :         }
     294                 :         10 :         fprintf(codefile,
     295                 :            :                 "if (len < 1) return ASN1_OVERRUN;\n"
     296                 :            :                 "p++; len--; ret++;\n");
     297                 :         10 :         fprintf(codefile,
     298                 :            :                 "do {\n"
     299                 :            :                 "if (len < 1) break;\n");
     300         [ +  + ]:        101 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     301         [ +  + ]:        102 :             while (m->val / 8 > pos / 8) {
     302                 :         11 :                 fprintf (codefile,
     303                 :            :                          "p++; len--; ret++;\n"
     304                 :            :                          "if (len < 1) break;\n");
     305                 :         11 :                 pos += 8;
     306                 :            :             }
     307                 :         91 :             fprintf (codefile,
     308                 :            :                      "(%s)->%s = (*p >> %d) & 1;\n",
     309                 :         91 :                      name, m->gen_name, 7 - m->val % 8);
     310                 :            :         }
     311                 :         10 :         fprintf(codefile,
     312                 :            :                 "} while(0);\n");
     313                 :         10 :         fprintf (codefile,
     314                 :            :                  "p += len; ret += len;\n");
     315                 :         10 :         break;
     316                 :            :     }
     317                 :            :     case TSequence: {
     318                 :            :         Member *m;
     319                 :            : 
     320         [ -  + ]:        169 :         if (t->members == NULL)
     321                 :          0 :             break;
     322                 :            : 
     323         [ +  + ]:        801 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     324                 :        632 :             char *s = NULL;
     325                 :            : 
     326         [ +  + ]:        632 :             if (m->ellipsis)
     327                 :         27 :                 continue;
     328                 :            : 
     329 [ +  - ][ -  + ]:        605 :             if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
     330         [ +  + ]:        605 :                           name, m->gen_name) < 0 || s == NULL)
     331                 :          0 :                 errx(1, "malloc");
     332                 :        605 :             decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL,
     333                 :            :                 depth + 1);
     334                 :        605 :             free (s);
     335                 :            :         }
     336                 :            : 
     337                 :        169 :         break;
     338                 :            :     }
     339                 :            :     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                 :            :     case TSetOf:
     407                 :            :     case TSequenceOf: {
     408                 :         72 :         char *n = NULL;
     409                 :         72 :         char *sname = NULL;
     410                 :            : 
     411                 :         72 :         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                 :         72 :         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 [ +  - ][ -  + ]:         72 :         if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL)
     444                 :          0 :             errx(1, "malloc");
     445 [ +  - ][ -  + ]:         72 :         if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL)
     446                 :          0 :             errx(1, "malloc");
     447                 :         72 :         decode_type (n, t->subtype, 0, forwstr, sname, NULL, depth + 1);
     448                 :         72 :         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         [ +  + ]:         72 :         if (t->range)
     457                 :          7 :             range_check(name, "len", forwstr, t->range);
     458                 :         72 :         free (n);
     459                 :         72 :         free (sname);
     460                 :         72 :         break;
     461                 :            :     }
     462                 :            :     case TGeneralizedTime:
     463                 :          6 :         decode_primitive ("generalized_time", name, forwstr);
     464                 :          6 :         break;
     465                 :            :     case TGeneralString:
     466                 :         14 :         decode_primitive ("general_string", name, forwstr);
     467                 :         14 :         break;
     468                 :            :     case TTeletexString:
     469                 :          1 :         decode_primitive ("general_string", name, forwstr);
     470                 :          1 :         break;
     471                 :            :     case TTag:{
     472                 :       1014 :         char *tname = NULL, *typestring = NULL;
     473                 :       1014 :         char *ide = NULL;
     474                 :            : 
     475 [ +  - ][ -  + ]:       1014 :         if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL)
     476                 :          0 :             errx(1, "malloc");
     477                 :            : 
     478                 :       1014 :         fprintf(codefile,
     479                 :            :                 "{\n"
     480                 :            :                 "size_t %s_datalen, %s_oldlen;\n"
     481                 :            :                 "Der_type %s;\n",
     482                 :            :                 tmpstr, tmpstr, typestring);
     483         [ +  + ]:       1014 :         if(support_ber)
     484                 :         41 :             fprintf(codefile,
     485                 :            :                     "int is_indefinite%u;\n", depth);
     486                 :            : 
     487                 :       1014 :         fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
     488                 :            :                 "&%s_datalen, &l);\n",
     489                 :       1014 :                 classname(t->tag.tagclass),
     490                 :            :                 typestring,
     491                 :       1014 :                 valuename(t->tag.tagclass, t->tag.tagvalue),
     492                 :            :                 tmpstr);
     493                 :            : 
     494                 :            :         /* XXX hardcode for now */
     495 [ +  + ][ +  + ]:       1014 :         if (support_ber && t->subtype->type == TOctetString) {
     496                 :          8 :             ide = typestring;
     497                 :            :         } else {
     498         [ +  + ]:       1006 :             fprintf(codefile,
     499                 :            :                     "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
     500                 :            :                     typestring,
     501                 :       1006 :                     is_primitive_type(t->subtype->type) ? "PRIM" : "CONS");
     502                 :            :         }
     503                 :            : 
     504         [ +  + ]:       1014 :         if(optional) {
     505                 :        223 :             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                 :        791 :             fprintf(codefile, "if(e) %s;\n", forwstr);
     514                 :            :         }
     515                 :       1014 :         fprintf (codefile,
     516                 :            :                  "p += l; len -= l; ret += l;\n"
     517                 :            :                  "%s_oldlen = len;\n",
     518                 :            :                  tmpstr);
     519         [ +  + ]:       1014 :         if(support_ber)
     520                 :         41 :             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                 :        973 :             fprintf(codefile,
     527                 :            :                     "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
     528                 :            :                     "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
     529 [ +  - ][ -  + ]:       1014 :         if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL)
     530                 :          0 :             errx(1, "malloc");
     531                 :       1014 :         decode_type (name, t->subtype, 0, forwstr, tname, ide, depth + 1);
     532         [ +  + ]:       1014 :         if(support_ber)
     533                 :         41 :             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                 :       1014 :         fprintf(codefile,
     549                 :            :                 "len = %s_oldlen - %s_datalen;\n",
     550                 :            :                 tmpstr, tmpstr);
     551         [ +  + ]:       1014 :         if(optional)
     552                 :        223 :             fprintf(codefile,
     553                 :            :                     "}\n");
     554                 :       1014 :         fprintf(codefile,
     555                 :            :                 "}\n");
     556                 :       1014 :         free(tname);
     557                 :       1014 :         free(typestring);
     558                 :       1014 :         break;
     559                 :            :     }
     560                 :            :     case TChoice: {
     561                 :         20 :         Member *m, *have_ellipsis = NULL;
     562                 :         20 :         const char *els = "";
     563                 :            : 
     564         [ -  + ]:         20 :         if (t->members == NULL)
     565                 :          0 :             break;
     566                 :            : 
     567         [ +  + ]:         86 :         ASN1_TAILQ_FOREACH(m, t->members, members) {
     568                 :         66 :             const Type *tt = m->type;
     569                 :         66 :             char *s = NULL;
     570                 :            :             Der_class cl;
     571                 :            :             Der_type  ty;
     572                 :            :             unsigned  tag;
     573                 :            : 
     574         [ +  + ]:         66 :             if (m->ellipsis) {
     575                 :          5 :                 have_ellipsis = m;
     576                 :          5 :                 continue;
     577                 :            :             }
     578                 :            : 
     579                 :         61 :             find_tag(tt, &cl, &ty, &tag);
     580                 :            : 
     581         [ +  + ]:         61 :             fprintf(codefile,
     582                 :            :                     "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
     583                 :            :                     els,
     584                 :            :                     classname(cl),
     585                 :         61 :                     ty ? "CONS" : "PRIM",
     586                 :            :                     valuename(cl, tag));
     587 [ +  - ][ -  + ]:         61 :             if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
     588         [ -  + ]:         61 :                           name, m->gen_name) < 0 || s == NULL)
     589                 :          0 :                 errx(1, "malloc");
     590                 :         61 :             decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL,
     591                 :            :                 depth + 1);
     592                 :         61 :             fprintf(codefile,
     593                 :            :                     "(%s)->element = %s;\n",
     594                 :            :                     name, m->label);
     595                 :         61 :             free(s);
     596                 :         61 :             fprintf(codefile,
     597                 :            :                     "}\n");
     598                 :         61 :             els = "else ";
     599                 :            :         }
     600         [ +  + ]:         20 :         if (have_ellipsis) {
     601                 :          5 :             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                 :         15 :             fprintf(codefile,
     622                 :            :                     "else {\n"
     623                 :            :                     "e = ASN1_PARSE_ERROR;\n"
     624                 :            :                     "%s;\n"
     625                 :            :                     "}\n",
     626                 :            :                     forwstr);
     627                 :            :         }
     628                 :         20 :         break;
     629                 :            :     }
     630                 :            :     case TUTCTime:
     631                 :          1 :         decode_primitive ("utctime", name, forwstr);
     632                 :          1 :         break;
     633                 :            :     case TUTF8String:
     634                 :         40 :         decode_primitive ("utf8string", name, forwstr);
     635                 :         40 :         break;
     636                 :            :     case TPrintableString:
     637                 :          1 :         decode_primitive ("printable_string", name, forwstr);
     638                 :          1 :         break;
     639                 :            :     case TIA5String:
     640                 :          4 :         decode_primitive ("ia5_string", name, forwstr);
     641                 :          4 :         break;
     642                 :            :     case TBMPString:
     643                 :          2 :         decode_primitive ("bmp_string", name, forwstr);
     644                 :          2 :         break;
     645                 :            :     case TUniversalString:
     646                 :          1 :         decode_primitive ("universal_string", name, forwstr);
     647                 :          1 :         break;
     648                 :            :     case TVisibleString:
     649                 :          1 :         decode_primitive ("visible_string", name, forwstr);
     650                 :          1 :         break;
     651                 :            :     case TNull:
     652                 :          3 :         fprintf (codefile, "/* NULL */\n");
     653                 :          3 :         break;
     654                 :            :     case TOID:
     655                 :         19 :         decode_primitive ("oid", name, forwstr);
     656                 :         19 :         break;
     657                 :            :     default :
     658                 :          0 :         abort ();
     659                 :            :     }
     660                 :       2048 :     return 0;
     661                 :            : }
     662                 :            : 
     663                 :            : void
     664                 :        296 : generate_type_decode (const Symbol *s)
     665                 :            : {
     666                 :        296 :     int preserve = preserve_type(s->name) ? TRUE : FALSE;
     667                 :            : 
     668                 :        296 :     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         [ +  - ]:        296 :     switch (s->type->type) {
     675                 :            :     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                 :        296 :         fprintf (codefile,
     700                 :            :                  "size_t ret = 0;\n"
     701                 :            :                  "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
     702                 :            :                  "int e HEIMDAL_UNUSED_ATTRIBUTE;\n");
     703         [ +  + ]:        296 :         if (preserve)
     704                 :          6 :             fprintf (codefile, "const unsigned char *begin = p;\n");
     705                 :            : 
     706                 :        296 :         fprintf (codefile, "\n");
     707                 :        296 :         fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
     708                 :            : 
     709                 :        296 :         decode_type ("data", s->type, 0, "goto fail", "Top", NULL, 1);
     710         [ +  + ]:        296 :         if (preserve)
     711                 :          6 :             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                 :        296 :         fprintf (codefile,
     719                 :            :                  "if(size) *size = ret;\n"
     720                 :            :                  "return 0;\n");
     721                 :        296 :         fprintf (codefile,
     722                 :            :                  "fail:\n"
     723                 :            :                  "free_%s(data);\n"
     724                 :            :                  "return e;\n",
     725                 :            :                  s->gen_name);
     726                 :            :         break;
     727                 :            :     default:
     728                 :          0 :         abort ();
     729                 :            :     }
     730                 :        296 :     fprintf (codefile, "}\n\n");
     731                 :        296 : }

Generated by: LCOV version 1.9