Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Portions Copyright (c) 2009 - 2010 Apple Inc. 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 : /*
37 : * Currently we generate C source code defining constant arrays of structures
38 : * containing a sort of a "byte-coded" template of an ASN.1 compiler to be
39 : * interpreted at run-time.
40 : */
41 :
42 : #include "gen_locl.h"
43 : #include <vis.h>
44 : #include <vis-extras.h>
45 :
46 : static const char *symbol_name(const char *, const Type *);
47 : static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
48 : Type *, int, int, int);
49 :
50 : static const char *
51 8721 : ttype_symbol(const char *basename, const Type *t)
52 : {
53 8721 : return t->symbol->gen_name;
54 : }
55 :
56 : static const char *
57 2337 : integer_symbol(const char *basename, const Type *t)
58 : {
59 2337 : if (t->members)
60 : /*
61 : * XXX enum foo -- compute the size either from inspecting the members
62 : * and applying the ABI's rules for enum size, OR infer the field
63 : * size from a template by using the offsetof field. The latter is
64 : * hard to do though.
65 : */
66 450 : return "int";
67 1862 : else if (t->range == NULL)
68 990 : return "heim_integer";
69 817 : else if (t->range->min < 0 &&
70 209 : (t->range->min < INT_MIN || t->range->max > INT_MAX))
71 0 : return "int64_t";
72 817 : else if (t->range->min < 0)
73 198 : return "int";
74 608 : else if (t->range->max > UINT_MAX)
75 0 : return "uint64_t";
76 : else
77 608 : return "unsigned";
78 : }
79 :
80 : static const char *
81 380 : boolean_symbol(const char *basename, const Type *t)
82 : {
83 380 : return "int";
84 : }
85 :
86 :
87 : static const char *
88 3553 : octetstring_symbol(const char *basename, const Type *t)
89 : {
90 3553 : return "heim_octet_string";
91 : }
92 :
93 : static const char *
94 76 : sequence_symbol(const char *basename, const Type *t)
95 : {
96 76 : return basename;
97 : }
98 :
99 : static const char *
100 304 : time_symbol(const char *basename, const Type *t)
101 : {
102 304 : return "time_t";
103 : }
104 :
105 : static const char *
106 5225 : tag_symbol(const char *basename, const Type *t)
107 : {
108 5225 : return symbol_name(basename, t->subtype);
109 : }
110 :
111 : static const char *
112 437 : generalstring_symbol(const char *basename, const Type *t)
113 : {
114 437 : return "heim_general_string";
115 : }
116 :
117 : static const char *
118 57 : printablestring_symbol(const char *basename, const Type *t)
119 : {
120 57 : return "heim_printable_string";
121 : }
122 :
123 : static const char *
124 361 : ia5string_symbol(const char *basename, const Type *t)
125 : {
126 361 : return "heim_ia5_string";
127 : }
128 :
129 : static const char *
130 38 : teletexstring_symbol(const char *basename, const Type *t)
131 : {
132 38 : return "heim_general_string";
133 : }
134 :
135 : static const char *
136 76 : visiblestring_symbol(const char *basename, const Type *t)
137 : {
138 76 : return "heim_visible_string";
139 : }
140 :
141 : static const char *
142 1216 : utf8string_symbol(const char *basename, const Type *t)
143 : {
144 1216 : return "heim_utf8_string";
145 : }
146 :
147 : static const char *
148 95 : bmpstring_symbol(const char *basename, const Type *t)
149 : {
150 95 : return "heim_bmp_string";
151 : }
152 :
153 : static const char *
154 38 : universalstring_symbol(const char *basename, const Type *t)
155 : {
156 38 : return "heim_universal_string";
157 : }
158 :
159 : static const char *
160 912 : oid_symbol(const char *basename, const Type *t)
161 : {
162 912 : return "heim_oid";
163 : }
164 :
165 : static const char *
166 570 : bitstring_symbol(const char *basename, const Type *t)
167 : {
168 570 : if (t->members)
169 570 : return basename;
170 0 : return "heim_bit_string";
171 : }
172 :
173 :
174 :
175 : /* Keep this sorted by `type' so we can just index this by type */
176 : const struct {
177 : enum typetype type;
178 : const char *(*symbol_name)(const char *, const Type *);
179 : int is_struct;
180 : } types[] = {
181 : { TBitString, bitstring_symbol, 0 },
182 : { TBoolean, boolean_symbol, 0 },
183 : { TChoice, sequence_symbol, 1 },
184 : { TEnumerated, integer_symbol, 0 },
185 : { TGeneralString, generalstring_symbol, 0 },
186 : { TTeletexString, teletexstring_symbol, 0 },
187 : { TGeneralizedTime, time_symbol, 0 },
188 : { TIA5String, ia5string_symbol, 0 },
189 : { TInteger, integer_symbol, 0 },
190 : { TNull, integer_symbol, 1 },
191 : { TOID, oid_symbol, 0 },
192 : { TOctetString, octetstring_symbol, 0 },
193 : { TPrintableString, printablestring_symbol, 0 },
194 : { TSequence, sequence_symbol, 1 },
195 : { TSequenceOf, tag_symbol, 1 },
196 : { TSet, sequence_symbol, 1 },
197 : { TSetOf, tag_symbol, 1 },
198 : { TTag, tag_symbol, 1 },
199 : { TType, ttype_symbol, 1 },
200 : { TUTCTime, time_symbol, 0 },
201 : { TUTF8String, utf8string_symbol, 0 },
202 : { TBMPString, bmpstring_symbol, 0 },
203 : { TUniversalString, universalstring_symbol, 0 },
204 : { TVisibleString, visiblestring_symbol, 0 },
205 : };
206 :
207 : static FILE *
208 93727 : get_code_file(void)
209 : {
210 89930 : if (!one_code_file)
211 0 : return templatefile;
212 93727 : return codefile;
213 : }
214 :
215 :
216 : static int
217 6859 : is_supported_type_p(const Type *t)
218 : {
219 13718 : return t->type >= 0 && t->type <= TVisibleString &&
220 6859 : types[t->type].type == t->type;
221 : }
222 :
223 : int
224 6859 : is_template_compat (const Symbol *s)
225 : {
226 6859 : return is_supported_type_p(s->type);
227 : }
228 :
229 : static const char *
230 24396 : symbol_name(const char *basename, const Type *t)
231 : {
232 24396 : if (t->type >= 0 && t->type <= TVisibleString &&
233 24396 : types[t->type].type == t->type)
234 24396 : return (types[t->type].symbol_name)(basename, t);
235 0 : if (t->type >= 0 && t->type <= TVisibleString)
236 0 : errx(1, "types[] is not sorted");
237 0 : errx(1, "unknown der type: %d\n", t->type);
238 : return NULL;
239 : }
240 :
241 :
242 : static char *
243 44042 : partial_offset(const char *basetype, const char *name, int need_offset, int isstruct)
244 : {
245 2318 : char *str;
246 44042 : if (name == NULL || need_offset == 0)
247 31008 : return strdup("0");
248 13720 : if (asprintf(&str, "offsetof(%s%s, %s)", isstruct ? "struct " : "", basetype, name) < 0 || str == NULL)
249 0 : errx(1, "malloc");
250 12348 : return str;
251 : }
252 :
253 : struct template {
254 : char *line;
255 : char *tt;
256 : char *offset;
257 : char *ptr;
258 : HEIM_TAILQ_ENTRY(template) members;
259 : };
260 :
261 : HEIM_TAILQ_HEAD(templatehead, template);
262 :
263 : struct tlist {
264 : char *name;
265 : char *header;
266 : struct templatehead template;
267 : HEIM_TAILQ_ENTRY(tlist) tmembers;
268 : };
269 :
270 : HEIM_TAILQ_HEAD(tlisthead, tlist);
271 :
272 : static void tlist_header(struct tlist *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
273 : static struct template *
274 : add_line(struct templatehead *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
275 : static int tlist_cmp(const struct tlist *, const struct tlist *);
276 :
277 : static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...)
278 : __attribute__ ((__format__ (__printf__, 4, 5)));
279 : static void add_line_string(struct templatehead *, const char *, const char *, const char *, ...)
280 : __attribute__ ((__format__ (__printf__, 4, 5)));
281 : static void add_line_pointer_reference(struct templatehead *, const char *, const char *, const char *, ...)
282 : __attribute__ ((__format__ (__printf__, 4, 5)));
283 :
284 :
285 : static struct tlisthead tlistmaster = HEIM_TAILQ_HEAD_INITIALIZER(tlistmaster);
286 : static unsigned long numdups = 0;
287 :
288 : static struct tlist *
289 31578 : tlist_new(const char *name)
290 : {
291 31578 : struct tlist *tl = calloc(1, sizeof(*tl));
292 31578 : tl->name = strdup(name);
293 31578 : HEIM_TAILQ_INIT(&tl->template);
294 31578 : return tl;
295 : }
296 :
297 : static void
298 31578 : tlist_header(struct tlist *t, const char *fmt, ...)
299 : {
300 1662 : va_list ap;
301 31578 : va_start(ap, fmt);
302 31578 : if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)
303 0 : errx(1, "malloc");
304 31578 : va_end(ap);
305 31578 : }
306 :
307 : static unsigned long
308 31008 : tlist_count(struct tlist *tl)
309 : {
310 31008 : unsigned int count = 0;
311 1632 : struct template *q;
312 :
313 88844 : HEIM_TAILQ_FOREACH(q, &tl->template, members) {
314 57836 : count++;
315 : }
316 31008 : return count;
317 : }
318 :
319 : static void
320 19665 : tlist_add(struct tlist *tl)
321 : {
322 19665 : HEIM_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers);
323 19660 : }
324 :
325 : static void
326 19665 : tlist_print(struct tlist *tl)
327 : {
328 1035 : struct template *q;
329 19665 : unsigned int i = 1;
330 19665 : FILE *f = get_code_file();
331 :
332 19665 : fprintf(f, "const struct asn1_template asn1_%s[] = {\n", tl->name);
333 19665 : fprintf(f, "/* 0 */ %s,\n", tl->header);
334 74062 : HEIM_TAILQ_FOREACH(q, &tl->template, members) {
335 54397 : int last = (HEIM_TAILQ_LAST(&tl->template, templatehead) == q);
336 56228 : fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
337 : }
338 19665 : fprintf(f, "};\n");
339 19665 : }
340 :
341 : static struct tlist *
342 13186 : tlist_find_by_name(const char *name)
343 : {
344 694 : struct tlist *ql;
345 524704 : HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
346 524704 : if (strcmp(ql->name, name) == 0)
347 13186 : return ql;
348 : }
349 0 : return NULL;
350 : }
351 :
352 : static int
353 6593 : tlist_cmp_name(const char *tname, const char *qname)
354 : {
355 6593 : struct tlist *tl = tlist_find_by_name(tname);
356 6593 : struct tlist *ql = tlist_find_by_name(qname);
357 6593 : if (tl == NULL)
358 0 : return 1;
359 6593 : if (ql == NULL)
360 0 : return -1;
361 6593 : return tlist_cmp(tl, ql);
362 : }
363 :
364 : static int
365 2442773 : tlist_cmp(const struct tlist *tl, const struct tlist *ql)
366 : {
367 128567 : int ret;
368 128567 : struct template *t, *q;
369 :
370 2442773 : if (tl == ql)
371 6246 : return 0;
372 2436180 : ret = strcmp(tl->header, ql->header);
373 2436180 : if (ret != 0) return ret;
374 :
375 29697 : q = HEIM_TAILQ_FIRST(&ql->template);
376 41591 : HEIM_TAILQ_FOREACH(t, &tl->template, members) {
377 29678 : if (q == NULL) return 1;
378 :
379 29678 : if (t->ptr == NULL || q->ptr == NULL) {
380 15656 : ret = strcmp(t->line, q->line);
381 15656 : if (ret != 0) return ret;
382 : } else {
383 14022 : ret = strcmp(t->tt, q->tt);
384 14022 : if (ret != 0) return ret;
385 :
386 6631 : ret = strcmp(t->offset, q->offset);
387 6631 : if (ret != 0) return ret;
388 :
389 12877 : if ((ret = strcmp(t->ptr, q->ptr)) != 0 ||
390 6593 : (ret = tlist_cmp_name(t->ptr, q->ptr)) != 0)
391 38 : return ret;
392 : }
393 11894 : q = HEIM_TAILQ_NEXT(q, members);
394 : }
395 11913 : if (q != NULL) return -1;
396 11286 : return 0;
397 : }
398 :
399 :
400 : static const char *
401 31483 : tlist_find_dup(const struct tlist *tl)
402 : {
403 1657 : struct tlist *ql;
404 :
405 2455750 : HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
406 2436180 : if (tlist_cmp(ql, tl) == 0) {
407 11913 : numdups++;
408 11913 : return ql->name;
409 : }
410 : }
411 18540 : return NULL;
412 : }
413 :
414 :
415 : /*
416 : * Add an entry to a template.
417 : */
418 :
419 : static struct template *
420 70319 : add_line(struct templatehead *t, const char *fmt, ...)
421 : {
422 70319 : struct template *q = calloc(1, sizeof(*q));
423 3701 : va_list ap;
424 70319 : va_start(ap, fmt);
425 70319 : if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
426 0 : errx(1, "malloc");
427 70319 : va_end(ap);
428 70319 : HEIM_TAILQ_INSERT_TAIL(t, q, members);
429 70319 : return q;
430 : }
431 :
432 : /*
433 : * Add an entry to a template, with the pointer field being a symbol name of a
434 : * template (i.e., an array, which decays to a pointer as usual in C).
435 : */
436 : static void
437 30381 : add_line_pointer(struct templatehead *t,
438 : const char *ptr,
439 : const char *offset,
440 : const char *ttfmt,
441 : ...)
442 : {
443 1599 : struct template *q;
444 1599 : va_list ap;
445 30381 : char *tt = NULL;
446 :
447 30381 : va_start(ap, ttfmt);
448 30381 : if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
449 0 : errx(1, "malloc");
450 30381 : va_end(ap);
451 :
452 30381 : if (ptr[0] == '&')
453 19 : q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr);
454 : else
455 30362 : q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
456 30381 : q->tt = tt;
457 30381 : q->offset = strdup(offset);
458 30381 : q->ptr = strdup(ptr);
459 30381 : }
460 :
461 : /*
462 : * Add an entry to a template where the pointer field is a string literal.
463 : */
464 : static void
465 17176 : add_line_string(struct templatehead *t,
466 : const char *str,
467 : const char *offset,
468 : const char *ttfmt,
469 : ...)
470 : {
471 904 : struct template *q;
472 904 : va_list ap;
473 17176 : char *tt = NULL;
474 :
475 17176 : va_start(ap, ttfmt);
476 17176 : if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
477 0 : errx(1, "malloc");
478 17176 : va_end(ap);
479 :
480 17176 : q = add_line(t, "{ %s, %s, \"%s\" }", tt, offset, str);
481 17176 : q->tt = tt;
482 17176 : q->offset = strdup(offset);
483 17176 : q->ptr = strdup(str);
484 17176 : }
485 :
486 : /*
487 : * Add an entry to a template, with the pointer field being a reference to
488 : * named object of a type other than a template or other array type.
489 : */
490 : static void
491 1938 : add_line_pointer_reference(struct templatehead *t,
492 : const char *ptr,
493 : const char *offset,
494 : const char *ttfmt,
495 : ...)
496 : {
497 102 : struct template *q;
498 102 : va_list ap;
499 1938 : char *tt = NULL;
500 :
501 1938 : va_start(ap, ttfmt);
502 1938 : if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
503 0 : errx(1, "malloc");
504 1938 : va_end(ap);
505 :
506 1938 : q = add_line(t, "{ %s, %s, (const void *)&asn1_%s }", tt, offset, ptr);
507 1938 : q->tt = tt;
508 1938 : q->offset = strdup(offset);
509 1938 : q->ptr = strdup(ptr);
510 1938 : }
511 :
512 : static int
513 16948 : use_extern(const Symbol *s)
514 : {
515 16948 : if (s->type == NULL)
516 1444 : return 1;
517 14688 : return 0;
518 : }
519 :
520 : static int
521 28901 : is_struct(const Type *t, int isstruct)
522 : {
523 29165 : if (t->type == TType)
524 7488 : return 0;
525 21261 : if (t->type == TSequence || t->type == TSet || t->type == TChoice)
526 3870 : return 1;
527 17176 : if (t->type == TTag)
528 5016 : return is_struct(t->subtype, isstruct);
529 :
530 12160 : if (t->type >= 0 && t->type <= TVisibleString &&
531 12160 : types[t->type].type == t->type) {
532 12160 : if (types[t->type].is_struct == 0)
533 9558 : return 0;
534 2071 : return isstruct;
535 : }
536 0 : if (t->type >= 0 && t->type <= TVisibleString)
537 0 : errx(1, "types[] is not sorted");
538 0 : errx(1, "unknown der type: %d\n", t->type);
539 : return isstruct;
540 : }
541 :
542 : static const Type *
543 72 : compact_tag(const Type *t)
544 : {
545 76 : while (t->type == TTag)
546 0 : t = t->subtype;
547 76 : return t;
548 : }
549 :
550 : static void
551 209 : defval(struct templatehead *temp, Member *m)
552 : {
553 209 : switch (m->defval->type) {
554 114 : case booleanvalue:
555 114 : add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)(uintptr_t)%u }",
556 108 : m->defval->u.booleanvalue);
557 114 : break;
558 0 : case nullvalue:
559 0 : add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)(uintptr_t)0 }");
560 0 : break;
561 95 : case integervalue: {
562 95 : const char *dv = "A1_DV_INTEGER";
563 95 : Type *t = m->type;
564 :
565 18 : for (;;) {
566 342 : if (t->range)
567 36 : break;
568 304 : if (t->type == TInteger && t->members)
569 54 : break;
570 247 : if (t->type == TEnumerated)
571 0 : break;
572 247 : if (t->subtype)
573 126 : t = t->subtype;
574 114 : else if (t->symbol && t->symbol->type)
575 108 : t = t->symbol->type;
576 : else
577 0 : errx(1, "DEFAULT values for unconstrained INTEGER members not supported");
578 : }
579 :
580 95 : if (t->members)
581 54 : dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions! No good! */
582 38 : else if (t->range && t->range->min < 0 &&
583 19 : (t->range->min < INT_MIN || t->range->max > INT_MAX))
584 0 : dv = "A1_DV_INTEGER64";
585 38 : else if (t->range && t->range->min < 0)
586 18 : dv = "A1_DV_INTEGER32";
587 19 : else if (t->range && t->range->max > UINT_MAX)
588 0 : dv = "A1_DV_INTEGER64";
589 : else
590 19 : dv = "A1_DV_INTEGER32";
591 95 : add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)(uintptr_t)%llu }",
592 95 : dv, (long long)m->defval->u.integervalue);
593 95 : break;
594 : }
595 0 : case stringvalue: {
596 0 : char *quoted;
597 :
598 0 : if (rk_strasvis("ed, m->defval->u.stringvalue,
599 : VIS_CSTYLE | VIS_NL, "\"") < 0)
600 0 : err(1, "Could not quote a string");
601 0 : add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)(uintptr_t)\"%s\" }",
602 : quoted);
603 0 : free(quoted);
604 0 : break;
605 : }
606 0 : case objectidentifiervalue: {
607 0 : struct objid *o;
608 0 : size_t sz = sizeof("{ }");
609 0 : char *s, *p;
610 0 : int len;
611 :
612 0 : for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
613 0 : if ((len = snprintf(0, 0, " %d", o->value)) < 0)
614 0 : err(1, "Could not format integer");
615 0 : sz += len;
616 : }
617 :
618 0 : if ((p = s = malloc(sz)) == NULL)
619 0 : err(1, "Could not allocate string");
620 :
621 0 : len = snprintf(p, sz, "{");
622 0 : sz -= len;
623 0 : p += len;
624 0 : for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
625 0 : if ((len = snprintf(p, sz, " %d", o->value)) < 0 || len > sz - 1)
626 0 : err(1, "Could not format integer");
627 0 : sz -= len;
628 0 : p += len;
629 : }
630 0 : if ((len = snprintf(p, sz, " }")) >= sz)
631 0 : abort();
632 0 : sz -= len;
633 0 : if (sz != 0)
634 0 : abort();
635 :
636 0 : add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)(uintptr_t)\"%s\" }", s);
637 0 : free(s);
638 0 : break;
639 : }
640 0 : default: abort();
641 : }
642 209 : }
643 :
644 : int
645 9424 : objid_cmp(struct objid *oida, struct objid *oidb)
646 : {
647 496 : struct objid *p;
648 496 : size_t ai, bi, alen, blen;
649 496 : int avals[20];
650 496 : int bvals[20];
651 496 : int c;
652 :
653 : /*
654 : * Our OID values are backwards here. Comparing them is hard.
655 : */
656 :
657 9424 : for (p = oida, alen = 0;
658 53561 : p && alen < sizeof(avals)/sizeof(avals[0]);
659 44137 : p = p->next)
660 44137 : avals[alen++] = p->value;
661 8928 : for (p = oidb, blen = 0;
662 57171 : p && blen < sizeof(bvals)/sizeof(bvals[0]);
663 47747 : p = p->next)
664 47747 : bvals[blen++] = p->value;
665 9424 : if (alen >= sizeof(avals)/sizeof(avals[0]) ||
666 496 : blen >= sizeof(bvals)/sizeof(bvals[0]))
667 0 : err(1, "OIDs with more components than %llu not supported",
668 : (unsigned long long)sizeof(avals)/sizeof(avals[0]));
669 :
670 36195 : for (ai = 0, bi = 0; ai < alen && bi < blen;)
671 36195 : if ((c = avals[(alen-1)-(ai++)] - bvals[(blen-1)-(bi++)]))
672 9424 : return c;
673 :
674 0 : if (ai == alen && bi == blen)
675 0 : return 0;
676 0 : if (ai == alen)
677 0 : return 1;
678 0 : return -1;
679 : }
680 :
681 : int
682 9424 : object_cmp(const void *va, const void *vb)
683 : {
684 9424 : const IOSObject *oa = *(const IOSObject * const *)va;
685 9424 : const IOSObject *ob = *(const IOSObject * const *)vb;
686 :
687 9424 : switch (oa->typeidf->value->type) {
688 0 : case booleanvalue:
689 0 : return oa->typeidf->value->u.booleanvalue -
690 0 : ob->typeidf->value->u.booleanvalue;
691 0 : case nullvalue:
692 0 : return 0;
693 0 : case integervalue:
694 0 : return oa->typeidf->value->u.integervalue -
695 0 : ob->typeidf->value->u.integervalue;
696 0 : case stringvalue:
697 0 : return strcmp(oa->typeidf->value->u.stringvalue,
698 0 : ob->typeidf->value->u.stringvalue);
699 9424 : case objectidentifiervalue: {
700 9424 : return objid_cmp(oa->typeidf->value->u.objectidentifiervalue,
701 9424 : ob->typeidf->value->u.objectidentifiervalue);
702 : }
703 0 : default:
704 0 : abort();
705 : return -1;
706 : }
707 : }
708 :
709 : void
710 304 : sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */
711 : Field *typeidfield, /* Field to sort by */
712 : IOSObject ***objectsp, /* Output: array of objects */
713 : size_t *nobjsp) /* Output: count of objects */
714 : {
715 16 : IOSObject **objects;
716 16 : IOSObject *o;
717 304 : size_t i, nobjs = 0;
718 :
719 304 : *objectsp = NULL;
720 :
721 3629 : HEIM_TAILQ_FOREACH(o, os->objects, objects) {
722 3325 : ObjectField *typeidobjf = NULL;
723 175 : ObjectField *of;
724 :
725 11115 : HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
726 7790 : if (strcmp(of->name, typeidfield->name) == 0)
727 3325 : typeidobjf = of;
728 : }
729 3325 : if (!typeidobjf) {
730 0 : warnx("Ignoring incomplete object specification of %s "
731 : "(missing type ID field)",
732 0 : o->symbol ? o->symbol->name : "<unknown>");
733 0 : continue;
734 : }
735 3325 : o->typeidf = typeidobjf;
736 3325 : nobjs++;
737 : }
738 304 : *nobjsp = nobjs;
739 :
740 304 : if (nobjs == 0)
741 0 : return;
742 :
743 304 : if ((objects = calloc(nobjs, sizeof(*objects))) == NULL)
744 0 : err(1, "Out of memory");
745 304 : *objectsp = objects;
746 :
747 304 : i = 0;
748 3629 : HEIM_TAILQ_FOREACH(o, os->objects, objects) {
749 3325 : ObjectField *typeidobjf = NULL;
750 175 : ObjectField *of;
751 :
752 11115 : HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
753 7790 : if (strcmp(of->name, typeidfield->name) == 0)
754 3325 : typeidobjf = of;
755 : }
756 3325 : if (typeidobjf)
757 3325 : objects[i++] = o;
758 : }
759 304 : qsort(objects, nobjs, sizeof(*objects), object_cmp);
760 : }
761 :
762 : static void
763 114 : template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
764 : {
765 114 : IOSObject **objects = NULL;
766 6 : IOSObject *o;
767 6 : struct tlist *tl;
768 6 : size_t nobjs, i;
769 :
770 114 : if (os->symbol->emitted_template)
771 19 : return;
772 :
773 95 : sort_object_set(os, typeidfield, &objects, &nobjs);
774 :
775 95 : tl = tlist_new(os->symbol->name);
776 95 : add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", os->symbol->name);
777 1069 : for (i = 0; i < nobjs; i++) {
778 969 : ObjectField *typeidobjf = NULL, *opentypeobjf = NULL;
779 51 : ObjectField *of;
780 969 : char *s = NULL;
781 :
782 969 : o = objects[i];
783 :
784 3287 : HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
785 2318 : if (strcmp(of->name, typeidfield->name) == 0)
786 918 : typeidobjf = of;
787 1349 : else if (strcmp(of->name, opentypefield->name) == 0)
788 969 : opentypeobjf = of;
789 : }
790 969 : if (!typeidobjf)
791 0 : continue; /* We've warned about this one already when sorting */
792 969 : if (!opentypeobjf) {
793 0 : warnx("Ignoring incomplete object specification of %s "
794 : "(missing open type field)",
795 0 : o->symbol ? o->symbol->name : "<unknown>");
796 0 : continue;
797 : }
798 :
799 969 : add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", o->symbol->name);
800 : /*
801 : * Some of this logic could stand to move into sanity checks of object
802 : * definitions in asn1parse.y.
803 : */
804 969 : switch (typeidobjf->value->type) {
805 0 : case integervalue:
806 0 : add_line(&tl->template,
807 : "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)(uintptr_t)%lld }",
808 0 : (long long)typeidobjf->value->u.integervalue);
809 0 : break;
810 969 : case objectidentifiervalue:
811 969 : if (asprintf(&s, "oid_%s",
812 1938 : typeidobjf->value->s->gen_name) == -1 || !s)
813 0 : err(1, "Out of memory");
814 969 : add_line_pointer_reference(&tl->template, s, "0", "A1_OP_OPENTYPE_ID");
815 969 : free(s);
816 969 : s = NULL;
817 969 : break;
818 0 : default:
819 0 : errx(1, "Only integer and OID types supported "
820 : "for open type type-ID fields");
821 : }
822 :
823 969 : if (asprintf(&s, "sizeof(%s)",
824 1938 : opentypeobjf->type->symbol->gen_name) == -1 || !s)
825 0 : err(1, "Out of memory");
826 969 : add_line_pointer_reference(&tl->template,
827 969 : opentypeobjf->type->symbol->gen_name, s,
828 : "A1_OP_OPENTYPE");
829 969 : free(s);
830 : }
831 95 : free(objects);
832 :
833 95 : tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nobjs);
834 95 : tlist_print(tl);
835 95 : tlist_add(tl);
836 95 : os->symbol->emitted_template = 1;
837 : }
838 :
839 : static void
840 114 : template_open_type(struct templatehead *temp,
841 : const char *basetype,
842 : const Type *t,
843 : size_t typeididx,
844 : size_t opentypeidx,
845 : Field *typeidfield,
846 : Field *opentypefield,
847 : Member *m,
848 : int is_array_of_open_type)
849 : {
850 114 : char *s = NULL;
851 :
852 114 : if (typeididx >= 1<<10 || opentypeidx >= 1<<10)
853 0 : errx(1, "SET/SEQUENCE with too many members (%s)", basetype);
854 :
855 114 : if (asprintf(&s, "offsetof(%s, _ioschoice_%s)",
856 114 : basetype, m->gen_name) == -1 || !s)
857 0 : err(1, "Out of memory");
858 :
859 114 : template_object_set(t->actual_parameter, typeidfield, opentypefield);
860 118 : add_line_pointer(temp, t->actual_parameter->symbol->gen_name, s,
861 : /*
862 : * We always sort object sets for now as we can't import
863 : * values yet, so they must all be known.
864 : */
865 : "A1_OP_OPENTYPE_OBJSET | A1_OS_IS_SORTED |%s | (%llu << 10) | %llu",
866 : is_array_of_open_type ? "A1_OS_OT_IS_ARRAY" : "0",
867 : (unsigned long long)opentypeidx,
868 : (unsigned long long)typeididx);
869 114 : free(s);
870 114 : }
871 :
872 : static void
873 3629 : template_names(struct templatehead *temp, const char *basetype, const Type *t)
874 : {
875 191 : Member *m;
876 :
877 3629 : add_line_string(temp, basetype, "0", "A1_OP_NAME");
878 17176 : HEIM_TAILQ_FOREACH(m, t->members, members) {
879 13547 : add_line_string(temp, m->name, "0", "A1_OP_NAME");
880 : }
881 3629 : }
882 :
883 : static void
884 44004 : template_members(struct templatehead *temp,
885 : const char *basetype,
886 : const char *name,
887 : const Type *t,
888 : int optional,
889 : int defaulted,
890 : int implicit,
891 : int isstruct,
892 : int need_offset)
893 : {
894 44004 : char *poffset = NULL;
895 :
896 44004 : if (optional && t->type != TTag && t->type != TType)
897 0 : errx(1, "%s...%s is optional and not a (TTag or TType)", basetype, name);
898 :
899 44004 : poffset = partial_offset(basetype, name, need_offset, isstruct);
900 :
901 44004 : switch (t->type) {
902 10089 : case TType:
903 10089 : if (use_extern(t->symbol)) {
904 1669 : add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s%s, %s, &asn1_extern_%s}",
905 : optional ? "|A1_FLAG_OPTIONAL" : "",
906 : defaulted ? "|A1_FLAG_DEFAULT" : "",
907 : implicit ? "|A1_FLAG_IMPLICIT" : "",
908 1368 : poffset, t->symbol->gen_name);
909 : } else {
910 9994 : add_line_pointer(temp, t->symbol->gen_name, poffset,
911 : "A1_OP_TYPE %s%s%s",
912 : optional ? "|A1_FLAG_OPTIONAL" : "",
913 : defaulted ? "|A1_FLAG_DEFAULT" : "",
914 : implicit ? "|A1_FLAG_IMPLICIT" : "");
915 :
916 : }
917 9558 : break;
918 1767 : case TEnumerated:
919 : case TInteger: {
920 1767 : char *varname = NULL;
921 1767 : char *itype = NULL;
922 :
923 1767 : if (t->members)
924 450 : itype = "IMEMBER";
925 1292 : else if (t->range == NULL)
926 702 : itype = "HEIM_INTEGER";
927 551 : else if (t->range->min < 0 &&
928 133 : (t->range->min < INT_MIN || t->range->max > INT_MAX))
929 0 : itype = "INTEGER64";
930 551 : else if (t->range->min < 0)
931 126 : itype = "INTEGER";
932 418 : else if (t->range->max > UINT_MAX)
933 0 : itype = "UNSIGNED64";
934 : else
935 418 : itype = "UNSIGNED";
936 :
937 : /*
938 : * If `t->members' then we should generate a template for those
939 : * members.
940 : *
941 : * We don't know the name of this field, and the type may not have a
942 : * name. If it has no name, we should generate a name for it, and if
943 : * it does have a name, use it, to name a template for its members.
944 : *
945 : * Then we could use that in _asn1_print() to pretty-print values of
946 : * enumerations.
947 : */
948 2242 : if (t->members && t->symbol) {
949 25 : struct tlist *tl;
950 25 : Member *m;
951 475 : size_t nmemb = 0;
952 :
953 475 : if (asprintf(&varname, "%s_enum_names", t->symbol->gen_name) == -1 ||
954 475 : varname == NULL)
955 0 : err(1, "Out of memory");
956 :
957 475 : tl = tlist_new(varname);
958 : /*
959 : * XXX We're going to assume that t->members is sorted in
960 : * numerically ascending order in the module source. We should
961 : * really sort it here.
962 : */
963 5928 : HEIM_TAILQ_FOREACH(m, t->members, members) {
964 5453 : if (m->val > UINT32_MAX)
965 0 : errx(1, "Cannot handle %s type %s with named bit %s "
966 : "larger than 63",
967 0 : t->type == TEnumerated ? "ENUMERATED" : "INTEGER",
968 : name, m->gen_name);
969 5453 : add_line(&tl->template,
970 5166 : "{ A1_OP_NAME, %d, \"%s\" }", (int)m->val, m->name);
971 5453 : nmemb++;
972 : }
973 475 : tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nmemb);
974 : /* XXX Accidentally O(N^2)? */
975 475 : if (!tlist_find_dup(tl)) {
976 475 : tlist_print(tl);
977 475 : tlist_add(tl);
978 : }
979 475 : add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, asn1_%s }", itype, poffset, varname);
980 : } else {
981 1292 : add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset);
982 : }
983 1767 : break;
984 : }
985 247 : case TGeneralString:
986 247 : add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);
987 247 : break;
988 19 : case TTeletexString:
989 19 : add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);
990 19 : break;
991 38 : case TPrintableString:
992 38 : add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);
993 38 : break;
994 2052 : case TOctetString:
995 2052 : add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);
996 2052 : break;
997 209 : case TIA5String:
998 209 : add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);
999 209 : break;
1000 57 : case TBMPString:
1001 57 : add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);
1002 57 : break;
1003 19 : case TUniversalString:
1004 19 : add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);
1005 19 : break;
1006 38 : case TVisibleString:
1007 38 : add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);
1008 38 : break;
1009 798 : case TUTF8String:
1010 798 : add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);
1011 798 : break;
1012 171 : case TGeneralizedTime:
1013 171 : add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);
1014 171 : break;
1015 19 : case TUTCTime:
1016 19 : add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);
1017 19 : break;
1018 247 : case TBoolean:
1019 247 : add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);
1020 247 : break;
1021 627 : case TOID:
1022 627 : add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);
1023 627 : break;
1024 72 : case TNull:
1025 72 : break;
1026 475 : case TBitString: {
1027 25 : struct templatehead template;
1028 25 : struct template *q;
1029 25 : Member *m;
1030 475 : size_t count = 0, i;
1031 475 : char *bname = NULL;
1032 475 : FILE *f = get_code_file();
1033 25 : static unsigned long bmember_counter = 0;
1034 :
1035 475 : HEIM_TAILQ_INIT(&template);
1036 :
1037 475 : if (HEIM_TAILQ_EMPTY(t->members)) {
1038 285 : add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset);
1039 285 : break;
1040 : }
1041 :
1042 200 : if (asprintf(&bname, "bmember_%s_%lu", name ? name : "", bmember_counter++) < 0 || bname == NULL)
1043 0 : errx(1, "malloc");
1044 190 : output_name(bname);
1045 :
1046 1862 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1047 1672 : if (m->val > UINT32_MAX)
1048 0 : errx(1, "Cannot handle BIT STRING type %s with named bit %s "
1049 : "larger than 63", name, m->gen_name);
1050 1672 : add_line(&template, "{ 0, %d, \"%s\" }", (int)m->val, m->gen_name);
1051 : }
1052 :
1053 1862 : HEIM_TAILQ_FOREACH(q, &template, members) {
1054 1672 : count++;
1055 : }
1056 :
1057 190 : fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);
1058 200 : fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)(uintptr_t)%lu) },\n",
1059 190 : rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",
1060 : basetype, (unsigned long)count);
1061 190 : i = 1;
1062 1862 : HEIM_TAILQ_FOREACH(q, &template, members) {
1063 1672 : int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
1064 1750 : fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
1065 : }
1066 190 : fprintf(f, "};\n");
1067 :
1068 190 : add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname);
1069 :
1070 190 : free(bname);
1071 :
1072 190 : break;
1073 : }
1074 0 : case TSet: {
1075 0 : Member *opentypemember = NULL;
1076 0 : Member *typeidmember = NULL;
1077 0 : Field *opentypefield = NULL;
1078 0 : Field *typeidfield = NULL;
1079 0 : Member *m;
1080 0 : struct decoration deco;
1081 0 : ssize_t more_deco = -1;
1082 0 : size_t i = 0, typeididx = 0, opentypeidx = 0;
1083 0 : int is_array_of_open_type = 0;
1084 :
1085 0 : if (isstruct && t->actual_parameter)
1086 0 : get_open_type_defn_fields(t, &typeidmember, &opentypemember,
1087 : &typeidfield, &opentypefield,
1088 : &is_array_of_open_type);
1089 :
1090 0 : fprintf(get_code_file(), "/* tset: members isstruct: %d */\n", isstruct);
1091 :
1092 0 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1093 0 : char *newbasename = NULL;
1094 :
1095 0 : if (m->ellipsis)
1096 0 : continue;
1097 :
1098 0 : if (typeidmember == m) typeididx = i;
1099 0 : if (opentypemember == m) opentypeidx = i;
1100 :
1101 0 : if (name) {
1102 0 : if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
1103 0 : errx(1, "malloc");
1104 : } else
1105 0 : newbasename = strdup(basetype);
1106 0 : if (newbasename == NULL)
1107 0 : errx(1, "malloc");
1108 :
1109 0 : if (m->defval)
1110 0 : defval(temp, m);
1111 :
1112 0 : template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
1113 :
1114 0 : free(newbasename);
1115 0 : i++;
1116 : }
1117 :
1118 0 : if (isstruct && t->actual_parameter)
1119 0 : template_open_type(temp, basetype, t, typeididx, opentypeidx,
1120 : typeidfield, opentypefield, opentypemember,
1121 : is_array_of_open_type);
1122 :
1123 0 : while (decorate_type(basetype, &deco, &more_deco)) {
1124 0 : char *poffset2;
1125 :
1126 0 : poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
1127 :
1128 0 : if (deco.ext) {
1129 0 : char *ptr = NULL;
1130 :
1131 : /* Decorated with external C type */
1132 0 : if (asprintf(&ptr, "&asn1_extern_%s_%s",
1133 0 : basetype, deco.field_name) == -1 || ptr == NULL)
1134 0 : err(1, "out of memory");
1135 0 : add_line_pointer(temp, ptr, poffset2,
1136 : "A1_OP_TYPE_DECORATE_EXTERN %s",
1137 0 : deco.opt ? "|A1_FLAG_OPTIONAL" : "");
1138 0 : free(ptr);
1139 : } else
1140 : /* Decorated with a templated ASN.1 type */
1141 0 : add_line_pointer(temp, deco.field_type, poffset2,
1142 : "A1_OP_TYPE_DECORATE %s",
1143 0 : deco.opt ? "|A1_FLAG_OPTIONAL" : "");
1144 0 : free(poffset2);
1145 0 : free(deco.field_type);
1146 : }
1147 :
1148 0 : if (isstruct)
1149 0 : template_names(temp, basetype, t);
1150 0 : break;
1151 : }
1152 3629 : case TSequence: {
1153 3629 : Member *opentypemember = NULL;
1154 3629 : Member *typeidmember = NULL;
1155 3629 : Field *opentypefield = NULL;
1156 3629 : Field *typeidfield = NULL;
1157 191 : Member *m;
1158 191 : struct decoration deco;
1159 3629 : ssize_t more_deco = -1;
1160 3629 : size_t i = 0, typeididx = 0, opentypeidx = 0;
1161 3629 : int is_array_of_open_type = 0;
1162 :
1163 3629 : if (isstruct && t->actual_parameter)
1164 114 : get_open_type_defn_fields(t, &typeidmember, &opentypemember,
1165 : &typeidfield, &opentypefield,
1166 : &is_array_of_open_type);
1167 :
1168 3820 : fprintf(get_code_file(), "/* tsequence: members isstruct: %d */\n", isstruct);
1169 :
1170 17176 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1171 13547 : char *newbasename = NULL;
1172 :
1173 13547 : if (m->ellipsis)
1174 551 : continue;
1175 :
1176 12996 : if (typeidmember == m) typeididx = i;
1177 12996 : if (opentypemember == m) opentypeidx = i;
1178 :
1179 12996 : if (name) {
1180 76 : if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
1181 0 : errx(1, "malloc");
1182 : } else
1183 12920 : newbasename = strdup(basetype);
1184 12996 : if (newbasename == NULL)
1185 0 : errx(1, "malloc");
1186 :
1187 12996 : if (m->defval)
1188 209 : defval(temp, m);
1189 :
1190 12996 : template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
1191 :
1192 12996 : free(newbasename);
1193 12996 : i++;
1194 : }
1195 :
1196 3629 : if (isstruct && t->actual_parameter)
1197 114 : template_open_type(temp, basetype, t, typeididx, opentypeidx,
1198 : typeidfield, opentypefield, opentypemember,
1199 : is_array_of_open_type);
1200 :
1201 3667 : while (decorate_type(basetype, &deco, &more_deco)) {
1202 2 : char *poffset2;
1203 :
1204 38 : poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
1205 :
1206 38 : if (deco.ext) {
1207 19 : char *ptr = NULL;
1208 :
1209 : /* Decorated with external C type */
1210 19 : if (asprintf(&ptr, "&asn1_extern_%s_%s",
1211 19 : basetype, deco.field_name) == -1 || ptr == NULL)
1212 0 : err(1, "out of memory");
1213 19 : add_line_pointer(temp, ptr, poffset2,
1214 : "A1_OP_TYPE_DECORATE_EXTERN %s",
1215 19 : deco.opt ? "|A1_FLAG_OPTIONAL" : "");
1216 19 : free(ptr);
1217 : } else
1218 : /* Decorated with a templated ASN.1 type */
1219 19 : add_line_pointer(temp, deco.field_type, poffset2,
1220 : "A1_OP_TYPE_DECORATE %s",
1221 19 : deco.opt ? "|A1_FLAG_OPTIONAL" : "");
1222 38 : free(poffset2);
1223 38 : free(deco.field_type);
1224 : }
1225 :
1226 3629 : if (isstruct)
1227 3629 : template_names(temp, basetype, t);
1228 3629 : break;
1229 : }
1230 21584 : case TTag: {
1231 21584 : char *tname = NULL, *elname = NULL;
1232 1136 : const char *sename, *dupname;
1233 21584 : int subtype_is_struct = is_struct(t->subtype, isstruct);
1234 1136 : static unsigned long tag_counter = 0;
1235 21584 : int tagimplicit = 0;
1236 52820 : int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
1237 34656 : t->tag.tagenv == TE_EXPLICIT) &&
1238 13072 : is_primitive_type(t->subtype);
1239 :
1240 21584 : if (t->tag.tagenv == TE_IMPLICIT) {
1241 1425 : Type *t2 = t->subtype;
1242 :
1243 1899 : while (t2->type == TType && (t2->subtype || t2->symbol->type))
1244 399 : t2 = t2->subtype ? t2->subtype : t2->symbol->type;
1245 1425 : if (t2->type != TChoice)
1246 1314 : tagimplicit = 1;
1247 : }
1248 :
1249 22720 : fprintf(get_code_file(), "/* template_members: %s %s %s */\n", basetype, implicit ? "imp" : "exp", tagimplicit ? "imp" : "exp");
1250 :
1251 21584 : if (subtype_is_struct)
1252 4698 : sename = basetype;
1253 : else
1254 16625 : sename = symbol_name(basetype, t->subtype);
1255 :
1256 22720 : if (asprintf(&tname, "tag_%s_%lu", name ? name : "", tag_counter++) < 0 || tname == NULL)
1257 0 : errx(1, "malloc");
1258 21584 : output_name(tname);
1259 :
1260 21584 : if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)
1261 0 : errx(1, "malloc");
1262 :
1263 21584 : generate_template_type(elname, &dupname, NULL, sename, name,
1264 21584 : t->subtype, 0, subtype_is_struct, 0);
1265 :
1266 66943 : add_line_pointer(temp, dupname, poffset,
1267 : "A1_TAG_T(%s,%s,%s)%s%s%s",
1268 21584 : classname(t->tag.tagclass),
1269 : prim ? "PRIM" : "CONS",
1270 21584 : valuename(t->tag.tagclass, t->tag.tagvalue),
1271 : optional ? "|A1_FLAG_OPTIONAL" : "",
1272 : defaulted ? "|A1_FLAG_DEFAULT" : "",
1273 : tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
1274 :
1275 21584 : free(tname);
1276 21584 : free(elname);
1277 :
1278 21584 : break;
1279 : }
1280 1425 : case TSetOf:
1281 : case TSequenceOf: {
1282 1425 : const char *type = NULL, *tname, *dupname;
1283 1425 : char *sename = NULL, *elname = NULL;
1284 1425 : int subtype_is_struct = is_struct(t->subtype, 0);
1285 75 : static unsigned long seof_counter = 0;
1286 :
1287 1425 : if (name && subtype_is_struct) {
1288 19 : tname = "seofTstruct";
1289 19 : if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)
1290 0 : errx(1, "malloc");
1291 1406 : } else if (subtype_is_struct) {
1292 19 : tname = "seofTstruct";
1293 19 : if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)
1294 0 : errx(1, "malloc");
1295 : } else {
1296 1387 : if (name)
1297 504 : tname = name;
1298 : else
1299 855 : tname = "seofTstruct";
1300 1387 : sename = strdup(symbol_name(basetype, t->subtype));
1301 : }
1302 1425 : if (sename == NULL)
1303 0 : errx(1, "malloc");
1304 :
1305 1425 : if (t->type == TSetOf) type = "A1_OP_SETOF";
1306 1102 : else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";
1307 0 : else abort();
1308 :
1309 1425 : if (asprintf(&elname, "%s_%s_%lu", basetype, tname, seof_counter++) < 0 || elname == NULL)
1310 0 : errx(1, "malloc");
1311 :
1312 1425 : generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,
1313 : 0, subtype_is_struct, need_offset);
1314 :
1315 1425 : add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname);
1316 1425 : free(sename);
1317 1425 : break;
1318 : }
1319 418 : case TChoice: {
1320 22 : struct decoration deco;
1321 418 : ssize_t more_deco = -1;
1322 22 : struct templatehead template;
1323 22 : struct template *q;
1324 418 : size_t count = 0, i;
1325 418 : char *tname = NULL;
1326 418 : FILE *f = get_code_file();
1327 22 : Member *m;
1328 418 : int ellipsis = 0;
1329 22 : char *e;
1330 22 : static unsigned long choice_counter = 0;
1331 :
1332 418 : HEIM_TAILQ_INIT(&template);
1333 :
1334 440 : if (asprintf(&tname, "asn1_choice_%s_%s%lu",
1335 418 : basetype, name ? name : "", choice_counter++) < 0 || tname == NULL)
1336 0 : errx(1, "malloc");
1337 :
1338 1634 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1339 64 : const char *dupname;
1340 1216 : char *elname = NULL;
1341 1216 : char *newbasename = NULL;
1342 64 : int subtype_is_struct;
1343 :
1344 1216 : if (m->ellipsis) {
1345 76 : ellipsis = 1;
1346 76 : continue;
1347 : }
1348 :
1349 1140 : subtype_is_struct = is_struct(m->type, 0);
1350 :
1351 1140 : if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)
1352 0 : errx(1, "malloc");
1353 :
1354 1140 : if (subtype_is_struct) {
1355 38 : if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)
1356 0 : errx(1, "malloc");
1357 : } else
1358 1102 : newbasename = strdup(basetype);
1359 :
1360 1140 : if (newbasename == NULL)
1361 0 : errx(1, "malloc");
1362 :
1363 :
1364 1140 : generate_template_type(elname, &dupname, NULL,
1365 1080 : symbol_name(newbasename, m->type),
1366 1140 : NULL, m->type, 0, subtype_is_struct, 1);
1367 :
1368 1200 : add_line(&template, "{ %s, offsetof(%s%s, u.%s), asn1_%s }",
1369 : m->label, isstruct ? "struct " : "",
1370 : basetype, m->gen_name,
1371 : dupname);
1372 :
1373 1140 : free(elname);
1374 1140 : free(newbasename);
1375 : }
1376 :
1377 1634 : HEIM_TAILQ_FOREACH(m, t->members, members) {
1378 1216 : add_line(&template, "{ 0, 0, \"%s\" }", m->name);
1379 : }
1380 :
1381 418 : e = NULL;
1382 418 : if (ellipsis) {
1383 80 : if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
1384 0 : errx(1, "malloc");
1385 : }
1386 :
1387 2774 : HEIM_TAILQ_FOREACH(q, &template, members) {
1388 2356 : count++;
1389 : }
1390 :
1391 418 : fprintf(f, "static const struct asn1_template %s[] = {\n", tname);
1392 814 : fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)(uintptr_t)%lu) },\n",
1393 418 : e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);
1394 418 : i = 1;
1395 2774 : HEIM_TAILQ_FOREACH(q, &template, members) {
1396 2356 : int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
1397 2458 : fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
1398 : }
1399 418 : fprintf(f, "};\n");
1400 :
1401 418 : add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
1402 :
1403 418 : while (decorate_type(basetype, &deco, &more_deco)) {
1404 0 : char *poffset2;
1405 :
1406 0 : poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
1407 :
1408 0 : if (deco.ext) {
1409 0 : char *ptr = NULL;
1410 :
1411 : /* Decorated with external C type */
1412 0 : if (asprintf(&ptr, "&asn1_extern_%s_%s",
1413 0 : basetype, deco.field_name) == -1 || ptr == NULL)
1414 0 : err(1, "out of memory");
1415 0 : add_line_pointer(temp, ptr, poffset2,
1416 : "A1_OP_TYPE_DECORATE_EXTERN %s",
1417 0 : deco.opt ? "|A1_FLAG_OPTIONAL" : "");
1418 0 : free(ptr);
1419 : } else
1420 : /* Decorated with a templated ASN.1 type */
1421 0 : add_line_pointer(temp, deco.field_type, poffset2,
1422 : "A1_OP_TYPE_DECORATE %s",
1423 0 : deco.opt ? "|A1_FLAG_OPTIONAL" : "");
1424 0 : free(poffset2);
1425 0 : free(deco.field_type);
1426 : }
1427 :
1428 418 : free(e);
1429 418 : free(tname);
1430 418 : break;
1431 : }
1432 0 : default:
1433 0 : abort ();
1434 : }
1435 44004 : if (poffset)
1436 44004 : free(poffset);
1437 44004 : }
1438 :
1439 : static void
1440 836 : gen_extern_stubs(FILE *f, const char *name)
1441 : {
1442 836 : fprintf(f,
1443 : "static const struct asn1_type_func asn1_extern_%s = {\n"
1444 : "\t(asn1_type_encode)encode_%s,\n"
1445 : "\t(asn1_type_decode)decode_%s,\n"
1446 : "\t(asn1_type_length)length_%s,\n"
1447 : "\t(asn1_type_copy)copy_%s,\n"
1448 : "\t(asn1_type_release)free_%s,\n"
1449 : "\t(asn1_type_print)print_%s,\n"
1450 : "\tsizeof(%s)\n"
1451 : "};\n",
1452 : name, name, name, name,
1453 : name, name, name, name);
1454 836 : }
1455 :
1456 : void
1457 1064 : gen_template_import(const Symbol *s)
1458 : {
1459 1064 : FILE *f = get_code_file();
1460 :
1461 1064 : if (template_flag == 0)
1462 216 : return;
1463 :
1464 836 : gen_extern_stubs(f, s->gen_name);
1465 : }
1466 :
1467 : void
1468 8930 : generate_template_type_forward(const char *name)
1469 : {
1470 9400 : fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n", name);
1471 8930 : }
1472 :
1473 : void
1474 95 : generate_template_objectset_forwards(const Symbol *s)
1475 : {
1476 95 : if (!template_flag)
1477 0 : return;
1478 95 : fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n",
1479 95 : s->gen_name);
1480 : }
1481 :
1482 : static void
1483 31008 : generate_template_type(const char *varname,
1484 : const char **dupname,
1485 : const char *symname,
1486 : const char *basetype,
1487 : const char *name,
1488 : Type *type,
1489 : int optional,
1490 : int isstruct,
1491 : int need_offset)
1492 : {
1493 1632 : struct tlist *tl;
1494 1632 : const char *d;
1495 31008 : char *szt = NULL;
1496 31008 : int have_ellipsis = 0;
1497 31008 : int implicit = 0;
1498 1632 : int n;
1499 :
1500 31008 : tl = tlist_new(varname);
1501 :
1502 31008 : if (type->type == TTag && type->tag.tagenv == TE_IMPLICIT) {
1503 513 : Type *t = type->subtype ? type->subtype : type->symbol->type;
1504 :
1505 551 : while (t->type == TType && (t->subtype || t->symbol->type))
1506 38 : t = t->subtype ? t->subtype : t->symbol->type;
1507 513 : if (t->type != TChoice)
1508 494 : implicit = (type->tag.tagenv == TE_IMPLICIT);
1509 : }
1510 :
1511 31008 : template_members(&tl->template, basetype, name, type, optional, 0,
1512 : implicit, isstruct, need_offset);
1513 :
1514 : /* if its a sequence or set type, check if there is a ellipsis */
1515 31008 : if (type->type == TSequence || type->type == TSet) {
1516 191 : Member *m;
1517 17176 : HEIM_TAILQ_FOREACH(m, type->members, members) {
1518 13547 : if (m->ellipsis)
1519 551 : have_ellipsis = 1;
1520 : }
1521 : }
1522 :
1523 31008 : if (isstruct)
1524 5035 : if (name)
1525 1026 : n = asprintf(&szt, "struct %s_%s", basetype, name);
1526 : else
1527 4009 : n = asprintf(&szt, "struct %s", basetype);
1528 : else
1529 25973 : n = asprintf(&szt, "%s", basetype);
1530 31008 : if (n < 0 || szt == NULL)
1531 0 : errx(1, "malloc");
1532 :
1533 31012 : if (HEIM_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull)
1534 0 : errx(1, "Tag %s...%s with no content ?", basetype, name ? name : "");
1535 :
1536 32640 : fprintf(get_code_file(), "/* generate_template_type: %s */\n", tl->name);
1537 :
1538 41104 : tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)(uintptr_t)%lu) }",
1539 6859 : (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",
1540 : have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl));
1541 :
1542 31008 : free(szt);
1543 :
1544 : /* XXX Accidentally O(N^2)? */
1545 31008 : d = tlist_find_dup(tl);
1546 31008 : if (d) {
1547 : #if 0
1548 : if (strcmp(d, tl->name) == 0)
1549 : errx(1, "found dup of ourself: %s", d);
1550 : #endif
1551 11913 : *dupname = d;
1552 : } else {
1553 19095 : *dupname = tl->name;
1554 19095 : tlist_print(tl);
1555 19095 : tlist_add(tl);
1556 : }
1557 31008 : }
1558 :
1559 :
1560 : void
1561 6859 : generate_template(const Symbol *s)
1562 : {
1563 6859 : FILE *f = get_code_file();
1564 361 : const char *dupname;
1565 361 : struct decoration deco;
1566 6859 : ssize_t more_deco = -1;
1567 :
1568 6859 : if (use_extern(s)) {
1569 0 : gen_extern_stubs(f, s->gen_name);
1570 0 : return;
1571 : }
1572 :
1573 6897 : while (decorate_type(s->gen_name, &deco, &more_deco)) {
1574 38 : if (!deco.ext)
1575 19 : continue;
1576 19 : if (deco.void_star && deco.header_name)
1577 0 : fprintf(f, "#include %s\n", deco.header_name);
1578 54 : fprintf(f,
1579 : "static const struct asn1_type_func asn1_extern_%s_%s = {\n"
1580 : "\t(asn1_type_encode)0,\n"
1581 : "\t(asn1_type_decode)0,\n"
1582 : "\t(asn1_type_length)0,\n"
1583 : "\t(asn1_type_copy)%s,\n"
1584 : "\t(asn1_type_release)%s,\n"
1585 : "\t(asn1_type_print)0,\n"
1586 : "\tsizeof(%s)\n"
1587 19 : "};\n", s->gen_name, deco.field_name,
1588 19 : deco.copy_function_name && deco.copy_function_name[0] ?
1589 : deco.copy_function_name : "0",
1590 19 : deco.free_function_name && deco.free_function_name[0] ?
1591 : deco.free_function_name : "0",
1592 19 : deco.void_star ? "void *" : deco.field_type);
1593 19 : free(deco.field_type);
1594 : }
1595 :
1596 6859 : generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
1597 :
1598 7581 : fprintf(f,
1599 : "\n"
1600 : "int ASN1CALL\n"
1601 : "decode_%s(const unsigned char *p, size_t len, %s *data, size_t *size)\n"
1602 : "{\n"
1603 : " memset(data, 0, sizeof(*data));\n"
1604 : " return _asn1_decode_top(asn1_%s, 0|%s, p, len, data, size);\n"
1605 : "}\n"
1606 : "\n",
1607 6859 : s->gen_name,
1608 6859 : s->gen_name,
1609 : dupname,
1610 6859 : support_ber ? "A1_PF_ALLOW_BER" : "0");
1611 :
1612 7220 : fprintf(f,
1613 : "\n"
1614 : "int ASN1CALL\n"
1615 : "encode_%s(unsigned char *p, size_t len, const %s *data, size_t *size)\n"
1616 : "{\n"
1617 : " return _asn1_encode%s(asn1_%s, p, len, data, size);\n"
1618 : "}\n"
1619 : "\n",
1620 6859 : s->gen_name,
1621 6859 : s->gen_name,
1622 : fuzzer_string,
1623 : dupname);
1624 :
1625 7220 : fprintf(f,
1626 : "\n"
1627 : "size_t ASN1CALL\n"
1628 : "length_%s(const %s *data)\n"
1629 : "{\n"
1630 : " return _asn1_length%s(asn1_%s, data);\n"
1631 : "}\n"
1632 : "\n",
1633 6859 : s->gen_name,
1634 6859 : s->gen_name,
1635 : fuzzer_string,
1636 : dupname);
1637 :
1638 :
1639 7220 : fprintf(f,
1640 : "\n"
1641 : "void ASN1CALL\n"
1642 : "free_%s(%s *data)\n"
1643 : "{\n"
1644 : " _asn1_free_top(asn1_%s, data);\n"
1645 : "}\n"
1646 : "\n",
1647 6859 : s->gen_name,
1648 6859 : s->gen_name,
1649 : dupname);
1650 :
1651 7220 : fprintf(f,
1652 : "\n"
1653 : "int ASN1CALL\n"
1654 : "copy_%s(const %s *from, %s *to)\n"
1655 : "{\n"
1656 : " return _asn1_copy_top(asn1_%s, from, to);\n"
1657 : "}\n"
1658 : "\n",
1659 6859 : s->gen_name,
1660 6498 : s->gen_name,
1661 6859 : s->gen_name,
1662 : dupname);
1663 :
1664 6859 : fprintf(f,
1665 : "\n"
1666 : "char * ASN1CALL\n"
1667 : "print_%s(const %s *data, int flags)\n"
1668 : "{\n"
1669 : " return _asn1_print_top(asn1_%s, flags, data);\n"
1670 : "}\n"
1671 : "\n",
1672 6859 : s->gen_name,
1673 6859 : s->gen_name,
1674 : dupname);
1675 : }
|