Home | History | Annotate | Line # | Download | only in asn1
      1 /*	$NetBSD: gen_copy.c,v 1.3 2023/06/19 21:41:42 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 - 2005 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "gen_locl.h"
     37 
     38 __RCSID("$NetBSD: gen_copy.c,v 1.3 2023/06/19 21:41:42 christos Exp $");
     39 
     40 static int used_fail;
     41 
     42 static void
     43 copy_primitive (const char *typename, const char *from, const char *to)
     44 {
     45     fprintf (codefile, "if(der_copy_%s(%s, %s)) goto fail;\n",
     46 	     typename, from, to);
     47     used_fail++;
     48 }
     49 
     50 static void
     51 copy_type (const char *from, const char *to, const Type *t, int preserve)
     52 {
     53     switch (t->type) {
     54     case TType:
     55 #if 0
     56 	copy_type (from, to, t->symbol->type, preserve);
     57 #endif
     58 	fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n",
     59 		 t->symbol->gen_name, from, to);
     60 	used_fail++;
     61 	break;
     62     case TInteger:
     63 	if (t->range == NULL && t->members == NULL) {
     64 	    copy_primitive ("heim_integer", from, to);
     65 	    break;
     66 	}
     67         /* fallthrough */
     68     case TBoolean:
     69     case TEnumerated :
     70 	fprintf(codefile, "*(%s) = *(%s);\n", to, from);
     71 	break;
     72     case TOctetString:
     73 	copy_primitive ("octet_string", from, to);
     74 	break;
     75     case TBitString:
     76 	if (ASN1_TAILQ_EMPTY(t->members))
     77 	    copy_primitive ("bit_string", from, to);
     78 	else
     79 	    fprintf(codefile, "*(%s) = *(%s);\n", to, from);
     80 	break;
     81     case TSet:
     82     case TSequence:
     83     case TChoice: {
     84 	Member *m, *have_ellipsis = NULL;
     85 
     86 	if(t->members == NULL)
     87 	    break;
     88 
     89 	if ((t->type == TSequence || t->type == TChoice) && preserve) {
     90 	    fprintf(codefile,
     91 		    "{ int ret;\n"
     92 		    "ret = der_copy_octet_string(&(%s)->_save, &(%s)->_save);\n"
     93 		    "if (ret) goto fail;\n"
     94 		    "}\n",
     95 		    from, to);
     96 	    used_fail++;
     97 	}
     98 
     99 	if(t->type == TChoice) {
    100 	    fprintf(codefile, "(%s)->element = (%s)->element;\n", to, from);
    101 	    fprintf(codefile, "switch((%s)->element) {\n", from);
    102 	}
    103 
    104 	ASN1_TAILQ_FOREACH(m, t->members, members) {
    105 	    char *fs;
    106 	    char *ts;
    107 
    108 	    if (m->ellipsis) {
    109 		have_ellipsis = m;
    110 		continue;
    111 	    }
    112 
    113 	    if(t->type == TChoice)
    114 		fprintf(codefile, "case %s:\n", m->label);
    115 
    116 	    if (asprintf (&fs, "%s(%s)->%s%s",
    117 			  m->optional ? "" : "&", from,
    118 			  t->type == TChoice ? "u." : "", m->gen_name) < 0)
    119 		errx(1, "malloc");
    120 	    if (fs == NULL)
    121 		errx(1, "malloc");
    122 	    if (asprintf (&ts, "%s(%s)->%s%s",
    123 			  m->optional ? "" : "&", to,
    124 			  t->type == TChoice ? "u." : "", m->gen_name) < 0)
    125 		errx(1, "malloc");
    126 	    if (ts == NULL)
    127 		errx(1, "malloc");
    128 	    if(m->optional){
    129 		fprintf(codefile, "if(%s) {\n", fs);
    130 		fprintf(codefile, "%s = malloc(sizeof(*%s));\n", ts, ts);
    131 		fprintf(codefile, "if(%s == NULL) goto fail;\n", ts);
    132 		used_fail++;
    133 	    }
    134 	    copy_type (fs, ts, m->type, FALSE);
    135 	    if(m->optional){
    136 		fprintf(codefile, "}else\n");
    137 		fprintf(codefile, "%s = NULL;\n", ts);
    138 	    }
    139 	    free (fs);
    140 	    free (ts);
    141 	    if(t->type == TChoice)
    142 		fprintf(codefile, "break;\n");
    143 	}
    144 	if(t->type == TChoice) {
    145 	    if (have_ellipsis) {
    146 		fprintf(codefile, "case %s: {\n"
    147 			"int ret;\n"
    148 			"ret=der_copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n"
    149 			"if (ret) goto fail;\n"
    150 			"break;\n"
    151 			"}\n",
    152 			have_ellipsis->label,
    153 			from, have_ellipsis->gen_name,
    154 			to, have_ellipsis->gen_name);
    155 		used_fail++;
    156 	    }
    157 	    fprintf(codefile, "}\n");
    158 	}
    159 	break;
    160     }
    161     case TSetOf:
    162     case TSequenceOf: {
    163 	char *f = NULL, *T = NULL;
    164 
    165 	fprintf (codefile, "if(((%s)->val = "
    166 		 "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
    167 		 to, from, to, from);
    168 	fprintf (codefile, "goto fail;\n");
    169 	used_fail++;
    170 	fprintf(codefile,
    171 		"for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n",
    172 		to, to, from, to);
    173 	if (asprintf(&f, "&(%s)->val[(%s)->len]", from, to) < 0)
    174 	    errx(1, "malloc");
    175 	if (f == NULL)
    176 	    errx(1, "malloc");
    177 	if (asprintf(&T, "&(%s)->val[(%s)->len]", to, to) < 0)
    178 	    errx(1, "malloc");
    179 	if (T == NULL)
    180 	    errx(1, "malloc");
    181 	copy_type(f, T, t->subtype, FALSE);
    182 	fprintf(codefile, "}\n");
    183 	free(f);
    184 	free(T);
    185 	break;
    186     }
    187     case TGeneralizedTime:
    188 	fprintf(codefile, "*(%s) = *(%s);\n", to, from);
    189 	break;
    190     case TGeneralString:
    191 	copy_primitive ("general_string", from, to);
    192 	break;
    193     case TTeletexString:
    194 	copy_primitive ("general_string", from, to);
    195 	break;
    196     case TUTCTime:
    197 	fprintf(codefile, "*(%s) = *(%s);\n", to, from);
    198 	break;
    199     case TUTF8String:
    200 	copy_primitive ("utf8string", from, to);
    201 	break;
    202     case TPrintableString:
    203 	copy_primitive ("printable_string", from, to);
    204 	break;
    205     case TIA5String:
    206 	copy_primitive ("ia5_string", from, to);
    207 	break;
    208     case TBMPString:
    209 	copy_primitive ("bmp_string", from, to);
    210 	break;
    211     case TUniversalString:
    212 	copy_primitive ("universal_string", from, to);
    213 	break;
    214     case TVisibleString:
    215 	copy_primitive ("visible_string", from, to);
    216 	break;
    217     case TTag:
    218 	copy_type (from, to, t->subtype, preserve);
    219 	break;
    220     case TOID:
    221 	copy_primitive ("oid", from, to);
    222 	break;
    223     case TNull:
    224 	break;
    225     default :
    226 	abort ();
    227     }
    228 }
    229 
    230 void
    231 generate_type_copy (const Symbol *s)
    232 {
    233   int preserve = preserve_type(s->name) ? TRUE : FALSE;
    234 
    235   used_fail = 0;
    236 
    237   fprintf (codefile, "int ASN1CALL\n"
    238 	   "copy_%s(const %s *from, %s *to)\n"
    239 	   "{\n"
    240 	   "memset(to, 0, sizeof(*to));\n",
    241 	   s->gen_name, s->gen_name, s->gen_name);
    242   copy_type ("from", "to", s->type, preserve);
    243   fprintf (codefile, "return 0;\n");
    244 
    245   if (used_fail)
    246       fprintf (codefile, "fail:\n"
    247 	       "free_%s(to);\n"
    248 	       "return ENOMEM;\n",
    249 	       s->gen_name);
    250 
    251   fprintf(codefile,
    252 	  "}\n\n");
    253 }
    254 
    255