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 : }
|