~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/asn1/gen_decode.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
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
    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
}
 
58
 
 
59
static int
 
60
is_primitive_type(int type)
 
61
{
 
62
    switch(type) {
 
63
    case TInteger:
 
64
    case TBoolean:
 
65
    case TOctetString:
 
66
    case TBitString:
 
67
    case TEnumerated:
 
68
    case TGeneralizedTime:
 
69
    case TGeneralString:
 
70
    case TOID:
 
71
    case TUTCTime:
 
72
    case TUTF8String:
 
73
    case TPrintableString:
 
74
    case TIA5String:
 
75
    case TBMPString:
 
76
    case TUniversalString:
 
77
    case TVisibleString:
 
78
    case TNull:
 
79
        return 1;
 
80
    default:
 
81
        return 0;
 
82
    }
 
83
}
 
84
 
 
85
static void
 
86
find_tag (const Type *t,
 
87
          Der_class *cl, Der_type *ty, unsigned *tag)
 
88
{
 
89
    switch (t->type) {
 
90
    case TBitString:
 
91
        *cl  = ASN1_C_UNIV;
 
92
        *ty  = PRIM;
 
93
        *tag = UT_BitString;
 
94
        break;
 
95
    case TBoolean:
 
96
        *cl  = ASN1_C_UNIV;
 
97
        *ty  = PRIM;
 
98
        *tag = UT_Boolean;
 
99
        break;
 
100
    case TChoice:
 
101
        errx(1, "Cannot have recursive CHOICE");
 
102
    case TEnumerated:
 
103
        *cl  = ASN1_C_UNIV;
 
104
        *ty  = PRIM;
 
105
        *tag = UT_Enumerated;
 
106
        break;
 
107
    case TGeneralString:
 
108
        *cl  = ASN1_C_UNIV;
 
109
        *ty  = PRIM;
 
110
        *tag = UT_GeneralString;
 
111
        break;
 
112
    case TGeneralizedTime:
 
113
        *cl  = ASN1_C_UNIV;
 
114
        *ty  = PRIM;
 
115
        *tag = UT_GeneralizedTime;
 
116
        break;
 
117
    case TIA5String:
 
118
        *cl  = ASN1_C_UNIV;
 
119
        *ty  = PRIM;
 
120
        *tag = UT_IA5String;
 
121
        break;
 
122
    case TInteger:
 
123
        *cl  = ASN1_C_UNIV;
 
124
        *ty  = PRIM;
 
125
        *tag = UT_Integer;
 
126
        break;
 
127
    case TNull:
 
128
        *cl  = ASN1_C_UNIV;
 
129
        *ty  = PRIM;
 
130
        *tag = UT_Null;
 
131
        break;
 
132
    case TOID:
 
133
        *cl  = ASN1_C_UNIV;
 
134
        *ty  = PRIM;
 
135
        *tag = UT_OID;
 
136
        break;
 
137
    case TOctetString:
 
138
        *cl  = ASN1_C_UNIV;
 
139
        *ty  = PRIM;
 
140
        *tag = UT_OctetString;
 
141
        break;
 
142
    case TPrintableString:
 
143
        *cl  = ASN1_C_UNIV;
 
144
        *ty  = PRIM;
 
145
        *tag = UT_PrintableString;
 
146
        break;
 
147
    case TSequence:
 
148
    case TSequenceOf:
 
149
        *cl  = ASN1_C_UNIV;
 
150
        *ty  = CONS;
 
151
        *tag = UT_Sequence;
 
152
        break;
 
153
    case TSet:
 
154
    case TSetOf:
 
155
        *cl  = ASN1_C_UNIV;
 
156
        *ty  = CONS;
 
157
        *tag = UT_Set;
 
158
        break;
 
159
    case TTag:
 
160
        *cl  = t->tag.tagclass;
 
161
        *ty  = is_primitive_type(t->subtype->type) ? PRIM : CONS;
 
162
        *tag = t->tag.tagvalue;
 
163
        break;
 
164
    case TType:
 
165
        if ((t->symbol->stype == Stype && t->symbol->type == NULL)
 
166
            || t->symbol->stype == SUndefined) {
 
167
            error_message("%s is imported or still undefined, "
 
168
                          " can't generate tag checking data in CHOICE "
 
169
                          "without this information",
 
170
                          t->symbol->name);
 
171
            exit(1);
 
172
        }
 
173
        find_tag(t->symbol->type, cl, ty, tag);
 
174
        return;
 
175
    case TUTCTime:
 
176
        *cl  = ASN1_C_UNIV;
 
177
        *ty  = PRIM;
 
178
        *tag = UT_UTCTime;
 
179
        break;
 
180
    case TUTF8String:
 
181
        *cl  = ASN1_C_UNIV;
 
182
        *ty  = PRIM;
 
183
        *tag = UT_UTF8String;
 
184
        break;
 
185
    case TBMPString:
 
186
        *cl  = ASN1_C_UNIV;
 
187
        *ty  = PRIM;
 
188
        *tag = UT_BMPString;
 
189
        break;
 
190
    case TUniversalString:
 
191
        *cl  = ASN1_C_UNIV;
 
192
        *ty  = PRIM;
 
193
        *tag = UT_UniversalString;
 
194
        break;
 
195
    case TVisibleString:
 
196
        *cl  = ASN1_C_UNIV;
 
197
        *ty  = PRIM;
 
198
        *tag = UT_VisibleString;
 
199
        break;
 
200
    default:
 
201
        abort();
 
202
    }
 
203
}
 
204
 
 
205
static void
 
206
range_check(const char *name,
 
207
            const char *length,
 
208
            const char *forwstr,
 
209
            struct range *r)
 
210
{
 
211
    if (r->min == r->max + 2 || r->min < r->max)
 
212
        fprintf (codefile,
 
213
                 "if ((%s)->%s > %d) {\n"
 
214
                 "e = ASN1_MAX_CONSTRAINT; %s;\n"
 
215
                 "}\n",
 
216
                 name, length, r->max, forwstr);
 
217
    if (r->min - 1 == r->max || r->min < r->max)
 
218
        fprintf (codefile,
 
219
                 "if ((%s)->%s < %d) {\n"
 
220
                 "e = ASN1_MIN_CONSTRAINT; %s;\n"
 
221
                 "}\n",
 
222
                 name, length, r->min, forwstr);
 
223
    if (r->max == r->min)
 
224
        fprintf (codefile,
 
225
                 "if ((%s)->%s != %d) {\n"
 
226
                 "e = ASN1_EXACT_CONSTRAINT; %s;\n"
 
227
                 "}\n",
 
228
                 name, length, r->min, forwstr);
 
229
}
 
230
 
 
231
static int
 
232
decode_type (const char *name, const Type *t, int optional,
 
233
             const char *forwstr, const char *tmpstr)
 
234
{
 
235
    switch (t->type) {
 
236
    case TType: {
 
237
        if (optional)
 
238
            fprintf(codefile,
 
239
                    "%s = calloc(1, sizeof(*%s));\n"
 
240
                    "if (%s == NULL) %s;\n",
 
241
                    name, name, name, forwstr);
 
242
        fprintf (codefile,
 
243
                 "e = decode_%s(p, len, %s, &l);\n",
 
244
                 t->symbol->gen_name, name);
 
245
        if (optional) {
 
246
            fprintf (codefile,
 
247
                     "if(e) {\n"
 
248
                     "free(%s);\n"
 
249
                     "%s = NULL;\n"
 
250
                     "} else {\n"
 
251
                     "p += l; len -= l; ret += l;\n"
 
252
                     "}\n",
 
253
                     name, name);
 
254
        } else {
 
255
            fprintf (codefile,
 
256
                     "if(e) %s;\n",
 
257
                     forwstr);
 
258
            fprintf (codefile,
 
259
                     "p += l; len -= l; ret += l;\n");
 
260
        }
 
261
        break;
 
262
    }
 
263
    case TInteger:
 
264
        if(t->members) {
 
265
            fprintf(codefile,
 
266
                    "{\n"
 
267
                    "int enumint;\n");
 
268
            decode_primitive ("integer", "&enumint", forwstr);
 
269
            fprintf(codefile,
 
270
                    "*%s = enumint;\n"
 
271
                    "}\n",
 
272
                    name);
 
273
        } else if (t->range == NULL) {
 
274
            decode_primitive ("heim_integer", name, forwstr);
 
275
        } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
 
276
            decode_primitive ("integer", name, forwstr);
 
277
        } else if (t->range->min == 0 && t->range->max == UINT_MAX) {
 
278
            decode_primitive ("unsigned", name, forwstr);
 
279
        } else if (t->range->min == 0 && t->range->max == INT_MAX) {
 
280
            decode_primitive ("unsigned", name, forwstr);
 
281
        } else
 
282
            errx(1, "%s: unsupported range %d -> %d",
 
283
                 name, t->range->min, t->range->max);
 
284
        break;
 
285
    case TBoolean:
 
286
      decode_primitive ("boolean", name, forwstr);
 
287
      break;
 
288
    case TEnumerated:
 
289
        decode_primitive ("enumerated", name, forwstr);
 
290
        break;
 
291
    case TOctetString:
 
292
        decode_primitive ("octet_string", name, forwstr);
 
293
        if (t->range)
 
294
            range_check(name, "length", forwstr, t->range);
 
295
        break;
 
296
    case TBitString: {
 
297
        Member *m;
 
298
        int pos = 0;
 
299
 
 
300
        if (ASN1_TAILQ_EMPTY(t->members)) {
 
301
            decode_primitive ("bit_string", name, forwstr);
 
302
            break;
 
303
        }
 
304
        fprintf(codefile,
 
305
                "if (len < 1) return ASN1_OVERRUN;\n"
 
306
                "p++; len--; ret++;\n");
 
307
        fprintf(codefile,
 
308
                "do {\n"
 
309
                "if (len < 1) break;\n");
 
310
        ASN1_TAILQ_FOREACH(m, t->members, members) {
 
311
            while (m->val / 8 > pos / 8) {
 
312
                fprintf (codefile,
 
313
                         "p++; len--; ret++;\n"
 
314
                         "if (len < 1) break;\n");
 
315
                pos += 8;
 
316
            }
 
317
            fprintf (codefile,
 
318
                     "(%s)->%s = (*p >> %d) & 1;\n",
 
319
                     name, m->gen_name, 7 - m->val % 8);
 
320
        }
 
321
        fprintf(codefile,
 
322
                "} while(0);\n");
 
323
        fprintf (codefile,
 
324
                 "p += len; ret += len;\n");
 
325
        break;
 
326
    }
 
327
    case TSequence: {
 
328
        Member *m;
 
329
 
 
330
        if (t->members == NULL)
 
331
            break;
 
332
 
 
333
        ASN1_TAILQ_FOREACH(m, t->members, members) {
 
334
            char *s;
 
335
 
 
336
            if (m->ellipsis)
 
337
                continue;
 
338
 
 
339
            asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
 
340
                      name, m->gen_name);
 
341
            if (s == NULL)
 
342
                errx(1, "malloc");
 
343
            decode_type (s, m->type, m->optional, forwstr, m->gen_name);
 
344
            free (s);
 
345
        }
 
346
        
 
347
        break;
 
348
    }
 
349
    case TSet: {
 
350
        Member *m;
 
351
        unsigned int memno;
 
352
 
 
353
        if(t->members == NULL)
 
354
            break;
 
355
 
 
356
        fprintf(codefile, "{\n");
 
357
        fprintf(codefile, "unsigned int members = 0;\n");
 
358
        fprintf(codefile, "while(len > 0) {\n");
 
359
        fprintf(codefile,
 
360
                "Der_class class;\n"
 
361
                "Der_type type;\n"
 
362
                "int tag;\n"
 
363
                "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
 
364
                "if(e) %s;\n", forwstr);
 
365
        fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
 
366
        memno = 0;
 
367
        ASN1_TAILQ_FOREACH(m, t->members, members) {
 
368
            char *s;
 
369
 
 
370
            assert(m->type->type == TTag);
 
371
 
 
372
            fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
 
373
                    classname(m->type->tag.tagclass),
 
374
                    is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS",
 
375
                    valuename(m->type->tag.tagclass, m->type->tag.tagvalue));
 
376
 
 
377
            asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
 
378
            if (s == NULL)
 
379
                errx(1, "malloc");
 
380
            if(m->optional)
 
381
                fprintf(codefile,
 
382
                        "%s = calloc(1, sizeof(*%s));\n"
 
383
                        "if (%s == NULL) { e = ENOMEM; %s; }\n",
 
384
                        s, s, s, forwstr);
 
385
            decode_type (s, m->type, 0, forwstr, m->gen_name);
 
386
            free (s);
 
387
 
 
388
            fprintf(codefile, "members |= (1 << %d);\n", memno);
 
389
            memno++;
 
390
            fprintf(codefile, "break;\n");
 
391
        }
 
392
        fprintf(codefile,
 
393
                "default:\n"
 
394
                "return ASN1_MISPLACED_FIELD;\n"
 
395
                "break;\n");
 
396
        fprintf(codefile, "}\n");
 
397
        fprintf(codefile, "}\n");
 
398
        memno = 0;
 
399
        ASN1_TAILQ_FOREACH(m, t->members, members) {
 
400
            char *s;
 
401
 
 
402
            asprintf (&s, "%s->%s", name, m->gen_name);
 
403
            if (s == NULL)
 
404
                errx(1, "malloc");
 
405
            fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno);
 
406
            if(m->optional)
 
407
                fprintf(codefile, "%s = NULL;\n", s);
 
408
            else if(m->defval)
 
409
                gen_assign_defval(s, m->defval);
 
410
            else
 
411
                fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
 
412
            free(s);
 
413
            memno++;
 
414
        }
 
415
        fprintf(codefile, "}\n");
 
416
        break;
 
417
    }
 
418
    case TSetOf:
 
419
    case TSequenceOf: {
 
420
        char *n;
 
421
        char *sname;
 
422
 
 
423
        fprintf (codefile,
 
424
                 "{\n"
 
425
                 "size_t %s_origlen = len;\n"
 
426
                 "size_t %s_oldret = ret;\n"
 
427
                 "size_t %s_olen = 0;\n"
 
428
                 "void *%s_tmp;\n"
 
429
                 "ret = 0;\n"
 
430
                 "(%s)->len = 0;\n"
 
431
                 "(%s)->val = NULL;\n",
 
432
                 tmpstr,
 
433
                 tmpstr,
 
434
                 tmpstr,
 
435
                 tmpstr,
 
436
                 name,
 
437
                 name);
 
438
 
 
439
        fprintf (codefile,
 
440
                 "while(ret < %s_origlen) {\n"
 
441
                 "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
 
442
                 "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
 
443
                 "%s_olen = %s_nlen;\n"
 
444
                 "%s_tmp = realloc((%s)->val, %s_olen);\n"
 
445
                 "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
 
446
                 "(%s)->val = %s_tmp;\n",
 
447
                 tmpstr,
 
448
                 tmpstr, tmpstr, name,
 
449
                 tmpstr, tmpstr, forwstr,
 
450
                 tmpstr, tmpstr,
 
451
                 tmpstr, name, tmpstr,
 
452
                 tmpstr, forwstr,
 
453
                 name, tmpstr);
 
454
 
 
455
        asprintf (&n, "&(%s)->val[(%s)->len]", name, name);
 
456
        if (n == NULL)
 
457
            errx(1, "malloc");
 
458
        asprintf (&sname, "%s_s_of", tmpstr);
 
459
        if (sname == NULL)
 
460
            errx(1, "malloc");
 
461
        decode_type (n, t->subtype, 0, forwstr, sname);
 
462
        fprintf (codefile,
 
463
                 "(%s)->len++;\n"
 
464
                 "len = %s_origlen - ret;\n"
 
465
                 "}\n"
 
466
                 "ret += %s_oldret;\n"
 
467
                 "}\n",
 
468
                 name,
 
469
                 tmpstr, tmpstr);
 
470
        if (t->range)
 
471
            range_check(name, "len", forwstr, t->range);
 
472
        free (n);
 
473
        free (sname);
 
474
        break;
 
475
    }
 
476
    case TGeneralizedTime:
 
477
        decode_primitive ("generalized_time", name, forwstr);
 
478
        break;
 
479
    case TGeneralString:
 
480
        decode_primitive ("general_string", name, forwstr);
 
481
        break;
 
482
    case TTag:{
 
483
        char *tname;
 
484
 
 
485
        fprintf(codefile,
 
486
                "{\n"
 
487
                "size_t %s_datalen, %s_oldlen;\n",
 
488
                tmpstr, tmpstr);
 
489
        if(dce_fix)
 
490
            fprintf(codefile,
 
491
                    "int dce_fix;\n");
 
492
        fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, %s, %s, "
 
493
                "&%s_datalen, &l);\n",
 
494
                classname(t->tag.tagclass),
 
495
                is_primitive_type(t->subtype->type) ? "PRIM" : "CONS",
 
496
                valuename(t->tag.tagclass, t->tag.tagvalue),
 
497
                tmpstr);
 
498
        if(optional) {
 
499
            fprintf(codefile,
 
500
                    "if(e) {\n"
 
501
                    "%s = NULL;\n"
 
502
                    "} else {\n"
 
503
                     "%s = calloc(1, sizeof(*%s));\n"
 
504
                     "if (%s == NULL) { e = ENOMEM; %s; }\n",
 
505
                     name, name, name, name, forwstr);
 
506
        } else {
 
507
            fprintf(codefile, "if(e) %s;\n", forwstr);
 
508
        }
 
509
        fprintf (codefile,
 
510
                 "p += l; len -= l; ret += l;\n"
 
511
                 "%s_oldlen = len;\n",
 
512
                 tmpstr);
 
513
        if(dce_fix)
 
514
            fprintf (codefile,
 
515
                     "if((dce_fix = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
 
516
                     "{ e = ASN1_BAD_FORMAT; %s; }\n",
 
517
                     tmpstr, forwstr);
 
518
        else
 
519
            fprintf(codefile,
 
520
                    "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
 
521
                    "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
 
522
        asprintf (&tname, "%s_Tag", tmpstr);
 
523
        if (tname == NULL)
 
524
            errx(1, "malloc");
 
525
        decode_type (name, t->subtype, 0, forwstr, tname);
 
526
        if(dce_fix)
 
527
            fprintf(codefile,
 
528
                    "if(dce_fix){\n"
 
529
                    "e = der_match_tag_and_length (p, len, "
 
530
                    "(Der_class)0,(Der_type)0, UT_EndOfContent, "
 
531
                    "&%s_datalen, &l);\n"
 
532
                    "if(e) %s;\np += l; len -= l; ret += l;\n"
 
533
                    "} else \n", tmpstr, forwstr);
 
534
        fprintf(codefile,
 
535
                "len = %s_oldlen - %s_datalen;\n",
 
536
                tmpstr, tmpstr);
 
537
        if(optional)
 
538
            fprintf(codefile,
 
539
                    "}\n");
 
540
        fprintf(codefile,
 
541
                "}\n");
 
542
        free(tname);
 
543
        break;
 
544
    }
 
545
    case TChoice: {
 
546
        Member *m, *have_ellipsis = NULL;
 
547
        const char *els = "";
 
548
 
 
549
        if (t->members == NULL)
 
550
            break;
 
551
 
 
552
        ASN1_TAILQ_FOREACH(m, t->members, members) {
 
553
            const Type *tt = m->type;
 
554
            char *s;
 
555
            Der_class cl;
 
556
            Der_type  ty;
 
557
            unsigned  tag;
 
558
        
 
559
            if (m->ellipsis) {
 
560
                have_ellipsis = m;
 
561
                continue;
 
562
            }
 
563
 
 
564
            find_tag(tt, &cl, &ty, &tag);
 
565
 
 
566
            fprintf(codefile,
 
567
                    "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
 
568
                    els,
 
569
                    classname(cl),
 
570
                    ty ? "CONS" : "PRIM",
 
571
                    valuename(cl, tag));
 
572
            asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
 
573
                      name, m->gen_name);
 
574
            if (s == NULL)
 
575
                errx(1, "malloc");
 
576
            decode_type (s, m->type, m->optional, forwstr, m->gen_name);
 
577
            fprintf(codefile,
 
578
                    "(%s)->element = %s;\n",
 
579
                    name, m->label);
 
580
            free(s);
 
581
            fprintf(codefile,
 
582
                    "}\n");
 
583
            els = "else ";
 
584
        }
 
585
        if (have_ellipsis) {
 
586
            fprintf(codefile,
 
587
                    "else {\n"
 
588
                    "(%s)->u.%s.data = calloc(1, len);\n"
 
589
                    "if ((%s)->u.%s.data == NULL) {\n"
 
590
                    "e = ENOMEM; %s;\n"
 
591
                    "}\n"
 
592
                    "(%s)->u.%s.length = len;\n"
 
593
                    "memcpy((%s)->u.%s.data, p, len);\n"
 
594
                    "(%s)->element = %s;\n"
 
595
                    "p += len;\n"
 
596
                    "ret += len;\n"
 
597
                    "len -= len;\n"
 
598
                    "}\n",
 
599
                    name, have_ellipsis->gen_name,
 
600
                    name, have_ellipsis->gen_name,
 
601
                    forwstr,
 
602
                    name, have_ellipsis->gen_name,
 
603
                    name, have_ellipsis->gen_name,
 
604
                    name, have_ellipsis->label);
 
605
        } else {
 
606
            fprintf(codefile,
 
607
                    "else {\n"
 
608
                    "e = ASN1_PARSE_ERROR;\n"
 
609
                    "%s;\n"
 
610
                    "}\n",
 
611
                    forwstr);
 
612
        }
 
613
        break;
 
614
    }
 
615
    case TUTCTime:
 
616
        decode_primitive ("utctime", name, forwstr);
 
617
        break;
 
618
    case TUTF8String:
 
619
        decode_primitive ("utf8string", name, forwstr);
 
620
        break;
 
621
    case TPrintableString:
 
622
        decode_primitive ("printable_string", name, forwstr);
 
623
        break;
 
624
    case TIA5String:
 
625
        decode_primitive ("ia5_string", name, forwstr);
 
626
        break;
 
627
    case TBMPString:
 
628
        decode_primitive ("bmp_string", name, forwstr);
 
629
        break;
 
630
    case TUniversalString:
 
631
        decode_primitive ("universal_string", name, forwstr);
 
632
        break;
 
633
    case TVisibleString:
 
634
        decode_primitive ("visible_string", name, forwstr);
 
635
        break;
 
636
    case TNull:
 
637
        fprintf (codefile, "/* NULL */\n");
 
638
        break;
 
639
    case TOID:
 
640
        decode_primitive ("oid", name, forwstr);
 
641
        break;
 
642
    default :
 
643
        abort ();
 
644
    }
 
645
    return 0;
 
646
}
 
647
 
 
648
void
 
649
generate_type_decode (const Symbol *s)
 
650
{
 
651
    int preserve = preserve_type(s->name) ? TRUE : FALSE;
 
652
 
 
653
    fprintf (headerfile,
 
654
             "int    "
 
655
             "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
 
656
             s->gen_name, s->gen_name);
 
657
 
 
658
    fprintf (codefile, "int\n"
 
659
             "decode_%s(const unsigned char *p,"
 
660
             " size_t len, %s *data, size_t *size)\n"
 
661
             "{\n",
 
662
             s->gen_name, s->gen_name);
 
663
 
 
664
    switch (s->type->type) {
 
665
    case TInteger:
 
666
    case TBoolean:
 
667
    case TOctetString:
 
668
    case TOID:
 
669
    case TGeneralizedTime:
 
670
    case TGeneralString:
 
671
    case TUTF8String:
 
672
    case TPrintableString:
 
673
    case TIA5String:
 
674
    case TBMPString:
 
675
    case TUniversalString:
 
676
    case TVisibleString:
 
677
    case TUTCTime:
 
678
    case TNull:
 
679
    case TEnumerated:
 
680
    case TBitString:
 
681
    case TSequence:
 
682
    case TSequenceOf:
 
683
    case TSet:
 
684
    case TSetOf:
 
685
    case TTag:
 
686
    case TType:
 
687
    case TChoice:
 
688
        fprintf (codefile,
 
689
                 "size_t ret = 0;\n"
 
690
                 "size_t l;\n"
 
691
                 "int e;\n");
 
692
        if (preserve)
 
693
            fprintf (codefile, "const unsigned char *begin = p;\n");
 
694
 
 
695
        fprintf (codefile, "\n");
 
696
        fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
 
697
 
 
698
        decode_type ("data", s->type, 0, "goto fail", "Top");
 
699
        if (preserve)
 
700
            fprintf (codefile,
 
701
                     "data->_save.data = calloc(1, ret);\n"
 
702
                     "if (data->_save.data == NULL) { \n"
 
703
                     "e = ENOMEM; goto fail; \n"
 
704
                     "}\n"
 
705
                     "data->_save.length = ret;\n"
 
706
                     "memcpy(data->_save.data, begin, ret);\n");
 
707
        fprintf (codefile,
 
708
                 "if(size) *size = ret;\n"
 
709
                 "return 0;\n");
 
710
        fprintf (codefile,
 
711
                 "fail:\n"
 
712
                 "free_%s(data);\n"
 
713
                 "return e;\n",
 
714
                 s->gen_name);
 
715
        break;
 
716
    default:
 
717
        abort ();
 
718
    }
 
719
    fprintf (codefile, "}\n\n");
 
720
}