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