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