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 Högskolan
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
copy_primitive(const char * typename,const char * from,const char * to)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
copy_type(const char * from,const char * to,const Type * t,int preserve)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
generate_type_copy(const Symbol * s)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