1/* $NetBSD: gen_decode.c,v 1.3 2023/06/19 21:41:42 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997 - 2006 Kungliga Tekniska H��gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "gen_locl.h" 37#include "lex.h" 38 39__RCSID("$NetBSD: gen_decode.c,v 1.3 2023/06/19 21:41:42 christos Exp $"); 40 41static void 42decode_primitive (const char *typename, const char *name, const char *forwstr) 43{ 44#if 0 45 fprintf (codefile, 46 "e = decode_%s(p, len, %s, &l);\n" 47 "%s;\n", 48 typename, 49 name, 50 forwstr); 51#else 52 fprintf (codefile, 53 "e = der_get_%s(p, len, %s, &l);\n" 54 "if(e) %s;\np += l; len -= l; ret += l;\n", 55 typename, 56 name, 57 forwstr); 58#endif 59} 60 61static void 62find_tag (const Type *t, 63 Der_class *cl, Der_type *ty, unsigned *tag) 64{ 65 switch (t->type) { 66 case TBitString: 67 *cl = ASN1_C_UNIV; 68 *ty = PRIM; 69 *tag = UT_BitString; 70 break; 71 case TBoolean: 72 *cl = ASN1_C_UNIV; 73 *ty = PRIM; 74 *tag = UT_Boolean; 75 break; 76 case TChoice: 77 errx(1, "Cannot have recursive CHOICE"); 78 case TEnumerated: 79 *cl = ASN1_C_UNIV; 80 *ty = PRIM; 81 *tag = UT_Enumerated; 82 break; 83 case TGeneralString: 84 *cl = ASN1_C_UNIV; 85 *ty = PRIM; 86 *tag = UT_GeneralString; 87 break; 88 case TTeletexString: 89 *cl = ASN1_C_UNIV; 90 *ty = PRIM; 91 *tag = UT_TeletexString; 92 break; 93 case TGeneralizedTime: 94 *cl = ASN1_C_UNIV; 95 *ty = PRIM; 96 *tag = UT_GeneralizedTime; 97 break; 98 case TIA5String: 99 *cl = ASN1_C_UNIV; 100 *ty = PRIM; 101 *tag = UT_IA5String; 102 break; 103 case TInteger: 104 *cl = ASN1_C_UNIV; 105 *ty = PRIM; 106 *tag = UT_Integer; 107 break; 108 case TNull: 109 *cl = ASN1_C_UNIV; 110 *ty = PRIM; 111 *tag = UT_Null; 112 break; 113 case TOID: 114 *cl = ASN1_C_UNIV; 115 *ty = PRIM; 116 *tag = UT_OID; 117 break; 118 case TOctetString: 119 *cl = ASN1_C_UNIV; 120 *ty = PRIM; 121 *tag = UT_OctetString; 122 break; 123 case TPrintableString: 124 *cl = ASN1_C_UNIV; 125 *ty = PRIM; 126 *tag = UT_PrintableString; 127 break; 128 case TSequence: 129 case TSequenceOf: 130 *cl = ASN1_C_UNIV; 131 *ty = CONS; 132 *tag = UT_Sequence; 133 break; 134 case TSet: 135 case TSetOf: 136 *cl = ASN1_C_UNIV; 137 *ty = CONS; 138 *tag = UT_Set; 139 break; 140 case TTag: 141 *cl = t->tag.tagclass; 142 *ty = is_primitive_type(t->subtype->type) ? PRIM : CONS; 143 *tag = t->tag.tagvalue; 144 break; 145 case TType: 146 if ((t->symbol->stype == Stype && t->symbol->type == NULL) 147 || t->symbol->stype == SUndefined) { 148 lex_error_message("%s is imported or still undefined, " 149 " can't generate tag checking data in CHOICE " 150 "without this information", 151 t->symbol->name); 152 exit(1); 153 } 154 find_tag(t->symbol->type, cl, ty, tag); 155 return; 156 case TUTCTime: 157 *cl = ASN1_C_UNIV; 158 *ty = PRIM; 159 *tag = UT_UTCTime; 160 break; 161 case TUTF8String: 162 *cl = ASN1_C_UNIV; 163 *ty = PRIM; 164 *tag = UT_UTF8String; 165 break; 166 case TBMPString: 167 *cl = ASN1_C_UNIV; 168 *ty = PRIM; 169 *tag = UT_BMPString; 170 break; 171 case TUniversalString: 172 *cl = ASN1_C_UNIV; 173 *ty = PRIM; 174 *tag = UT_UniversalString; 175 break; 176 case TVisibleString: 177 *cl = ASN1_C_UNIV; 178 *ty = PRIM; 179 *tag = UT_VisibleString; 180 break; 181 default: 182 abort(); 183 } 184} 185 186static void 187range_check(const char *name, 188 const char *length, 189 const char *forwstr, 190 struct range *r) 191{ 192 if (r->min == r->max + 2 || r->min < r->max) 193 fprintf (codefile, 194 "if ((%s)->%s > %lld) {\n" 195 "e = ASN1_MAX_CONSTRAINT; %s;\n" 196 "}\n", 197 name, length, (long long)r->max, forwstr); 198 if ((r->min - 1 == r->max || r->min < r->max) && r->min > 0) 199 fprintf (codefile, 200 "if ((%s)->%s < %lld) {\n" 201 "e = ASN1_MIN_CONSTRAINT; %s;\n" 202 "}\n", 203 name, length, (long long)r->min, forwstr); 204 if (r->max == r->min) 205 fprintf (codefile, 206 "if ((%s)->%s != %lld) {\n" 207 "e = ASN1_EXACT_CONSTRAINT; %s;\n" 208 "}\n", 209 name, length, (long long)r->min, forwstr); 210} 211 212static int 213decode_type (const char *name, const Type *t, int optional, 214 const char *forwstr, const char *tmpstr, const char *dertype, 215 unsigned int depth) 216{ 217 switch (t->type) { 218 case TType: { 219 if (optional) 220 fprintf(codefile, 221 "%s = calloc(1, sizeof(*%s));\n" 222 "if (%s == NULL) %s;\n", 223 name, name, name, forwstr); 224 fprintf (codefile, 225 "e = decode_%s(p, len, %s, &l);\n", 226 t->symbol->gen_name, name); 227 if (optional) { 228 fprintf (codefile, 229 "if(e) {\n" 230 "free(%s);\n" 231 "%s = NULL;\n" 232 "} else {\n" 233 "p += l; len -= l; ret += l;\n" 234 "}\n", 235 name, name); 236 } else { 237 fprintf (codefile, 238 "if(e) %s;\n", 239 forwstr); 240 fprintf (codefile, 241 "p += l; len -= l; ret += l;\n"); 242 } 243 break; 244 } 245 case TInteger: 246 if(t->members) { 247 /* 248 * This will produce a worning, how its hard to fix since: 249 * if its enum to an NameType, we can add appriate 250 * type-cast. If its not though, we have to figure out if 251 * there is negative enum enum and use appropriate 252 * signness and size on the intertype we cast the result 253 * too. 254 */ 255 fprintf(codefile, 256 "{\n" 257 "int enumint;\n"); 258 decode_primitive ("integer", "&enumint", forwstr); 259 fprintf(codefile, 260 "*%s = enumint;\n" 261 "}\n", 262 name); 263 } else if (t->range == NULL) { 264 decode_primitive ("heim_integer", name, forwstr); 265 } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) { 266 decode_primitive ("integer64", name, forwstr); 267 } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { 268 decode_primitive ("unsigned64", name, forwstr); 269 } else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) { 270 decode_primitive ("integer", name, forwstr); 271 } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { 272 decode_primitive ("unsigned", name, forwstr); 273 } else 274 errx(1, "%s: unsupported range %lld -> %lld", 275 name, (long long)t->range->min, (long long)t->range->max); 276 break; 277 case TBoolean: 278 decode_primitive ("boolean", name, forwstr); 279 break; 280 case TEnumerated: 281 decode_primitive ("enumerated", name, forwstr); 282 break; 283 case TOctetString: 284 if (dertype) { 285 fprintf(codefile, 286 "if (%s == CONS) {\n", 287 dertype); 288 decode_primitive("octet_string_ber", name, forwstr); 289 fprintf(codefile, 290 "} else {\n"); 291 } 292 decode_primitive ("octet_string", name, forwstr); 293 if (dertype) 294 fprintf(codefile, "}\n"); 295 if (t->range) 296 range_check(name, "length", forwstr, t->range); 297 break; 298 case TBitString: { 299 Member *m; 300 int pos = 0; 301 302 if (ASN1_TAILQ_EMPTY(t->members)) { 303 decode_primitive ("bit_string", name, forwstr); 304 break; 305 } 306 fprintf(codefile, 307 "if (len < 1) return ASN1_OVERRUN;\n" 308 "p++; len--; ret++;\n"); 309 fprintf(codefile, 310 "do {\n" 311 "if (len < 1) break;\n"); 312 ASN1_TAILQ_FOREACH(m, t->members, members) { 313 while (m->val / 8 > pos / 8) { 314 fprintf (codefile, 315 "p++; len--; ret++;\n" 316 "if (len < 1) break;\n"); 317 pos += 8; 318 } 319 fprintf (codefile, 320 "(%s)->%s = (*p >> %d) & 1;\n", 321 name, m->gen_name, 7 - m->val % 8); 322 } 323 fprintf(codefile, 324 "} while(0);\n"); 325 fprintf (codefile, 326 "p += len; ret += len;\n"); 327 break; 328 } 329 case TSequence: { 330 Member *m; 331 332 if (t->members == NULL) 333 break; 334 335 ASN1_TAILQ_FOREACH(m, t->members, members) { 336 char *s = NULL; 337 338 if (m->ellipsis) 339 continue; 340 341 if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", 342 name, m->gen_name) < 0 || s == NULL) 343 errx(1, "malloc"); 344 decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, 345 depth + 1); 346 free (s); 347 } 348 349 break; 350 } 351 case TSet: { 352 Member *m; 353 unsigned int memno; 354 355 if(t->members == NULL) 356 break; 357 358 fprintf(codefile, "{\n"); 359 fprintf(codefile, "unsigned int members = 0;\n"); 360 fprintf(codefile, "while(len > 0) {\n"); 361 fprintf(codefile, 362 "Der_class class;\n" 363 "Der_type type;\n" 364 "int tag;\n" 365 "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n" 366 "if(e) %s;\n", forwstr); 367 fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n"); 368 memno = 0; 369 ASN1_TAILQ_FOREACH(m, t->members, members) { 370 char *s; 371 372 assert(m->type->type == TTag); 373 374 fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n", 375 classname(m->type->tag.tagclass), 376 is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS", 377 valuename(m->type->tag.tagclass, m->type->tag.tagvalue)); 378 379 if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL) 380 errx(1, "malloc"); 381 if(m->optional) 382 fprintf(codefile, 383 "%s = calloc(1, sizeof(*%s));\n" 384 "if (%s == NULL) { e = ENOMEM; %s; }\n", 385 s, s, s, forwstr); 386 decode_type (s, m->type, 0, forwstr, m->gen_name, NULL, depth + 1); 387 free (s); 388 389 fprintf(codefile, "members |= (1 << %d);\n", memno); 390 memno++; 391 fprintf(codefile, "break;\n"); 392 } 393 fprintf(codefile, 394 "default:\n" 395 "return ASN1_MISPLACED_FIELD;\n" 396 "break;\n"); 397 fprintf(codefile, "}\n"); 398 fprintf(codefile, "}\n"); 399 memno = 0; 400 ASN1_TAILQ_FOREACH(m, t->members, members) { 401 char *s; 402 403 if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || 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 = NULL; 421 char *sname = NULL; 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 if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL) 456 errx(1, "malloc"); 457 if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL) 458 errx(1, "malloc"); 459 decode_type (n, t->subtype, 0, forwstr, sname, NULL, depth + 1); 460 fprintf (codefile, 461 "(%s)->len++;\n" 462 "len = %s_origlen - ret;\n" 463 "}\n" 464 "ret += %s_oldret;\n" 465 "}\n", 466 name, 467 tmpstr, tmpstr); 468 if (t->range) 469 range_check(name, "len", forwstr, t->range); 470 free (n); 471 free (sname); 472 break; 473 } 474 case TGeneralizedTime: 475 decode_primitive ("generalized_time", name, forwstr); 476 break; 477 case TGeneralString: 478 decode_primitive ("general_string", name, forwstr); 479 break; 480 case TTeletexString: 481 decode_primitive ("general_string", name, forwstr); 482 break; 483 case TTag:{ 484 char *tname = NULL, *typestring = NULL; 485 char *ide = NULL; 486 487 if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL) 488 errx(1, "malloc"); 489 490 fprintf(codefile, 491 "{\n" 492 "size_t %s_datalen, %s_oldlen;\n" 493 "Der_type %s;\n", 494 tmpstr, tmpstr, typestring); 495 if(support_ber) 496 fprintf(codefile, 497 "int is_indefinite%u;\n", depth); 498 499 fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, " 500 "&%s_datalen, &l);\n", 501 classname(t->tag.tagclass), 502 typestring, 503 valuename(t->tag.tagclass, t->tag.tagvalue), 504 tmpstr); 505 506 /* XXX hardcode for now */ 507 if (support_ber && t->subtype->type == TOctetString) { 508 ide = typestring; 509 } else { 510 fprintf(codefile, 511 "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n", 512 typestring, 513 is_primitive_type(t->subtype->type) ? "PRIM" : "CONS"); 514 } 515 516 if(optional) { 517 fprintf(codefile, 518 "if(e) {\n" 519 "%s = NULL;\n" 520 "} else {\n" 521 "%s = calloc(1, sizeof(*%s));\n" 522 "if (%s == NULL) { e = ENOMEM; %s; }\n", 523 name, name, name, name, forwstr); 524 } else { 525 fprintf(codefile, "if(e) %s;\n", forwstr); 526 } 527 fprintf (codefile, 528 "p += l; len -= l; ret += l;\n" 529 "%s_oldlen = len;\n", 530 tmpstr); 531 if(support_ber) 532 fprintf (codefile, 533 "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n" 534 "{ e = ASN1_BAD_FORMAT; %s; }\n" 535 "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }", 536 depth, tmpstr, forwstr, depth, forwstr); 537 else 538 fprintf(codefile, 539 "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n" 540 "len = %s_datalen;\n", tmpstr, forwstr, tmpstr); 541 if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL) 542 errx(1, "malloc"); 543 decode_type (name, t->subtype, 0, forwstr, tname, ide, depth + 1); 544 if(support_ber) 545 fprintf(codefile, 546 "if(is_indefinite%u){\n" 547 "len += 2;\n" 548 "e = der_match_tag_and_length(p, len, " 549 "(Der_class)0, &%s, UT_EndOfContent, " 550 "&%s_datalen, &l);\n" 551 "if(e) %s;\n" 552 "p += l; len -= l; ret += l;\n" 553 "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n" 554 "} else \n", 555 depth, 556 typestring, 557 tmpstr, 558 forwstr, 559 typestring, forwstr); 560 fprintf(codefile, 561 "len = %s_oldlen - %s_datalen;\n", 562 tmpstr, tmpstr); 563 if(optional) 564 fprintf(codefile, 565 "}\n"); 566 fprintf(codefile, 567 "}\n"); 568 free(tname); 569 free(typestring); 570 break; 571 } 572 case TChoice: { 573 Member *m, *have_ellipsis = NULL; 574 const char *els = ""; 575 576 if (t->members == NULL) 577 break; 578 579 ASN1_TAILQ_FOREACH(m, t->members, members) { 580 const Type *tt = m->type; 581 char *s = NULL; 582 Der_class cl; 583 Der_type ty; 584 unsigned tag; 585 586 if (m->ellipsis) { 587 have_ellipsis = m; 588 continue; 589 } 590 591 find_tag(tt, &cl, &ty, &tag); 592 593 fprintf(codefile, 594 "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n", 595 els, 596 classname(cl), 597 ty ? "CONS" : "PRIM", 598 valuename(cl, tag)); 599 fprintf(codefile, 600 "(%s)->element = %s;\n", 601 name, m->label); 602 if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&", 603 name, m->gen_name) < 0 || s == NULL) 604 errx(1, "malloc"); 605 decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, 606 depth + 1); 607 free(s); 608 fprintf(codefile, 609 "}\n"); 610 els = "else "; 611 } 612 if (have_ellipsis) { 613 fprintf(codefile, 614 "else {\n" 615 "(%s)->element = %s;\n" 616 "(%s)->u.%s.data = calloc(1, len);\n" 617 "if ((%s)->u.%s.data == NULL) {\n" 618 "e = ENOMEM; %s;\n" 619 "}\n" 620 "(%s)->u.%s.length = len;\n" 621 "memcpy((%s)->u.%s.data, p, len);\n" 622 "p += len;\n" 623 "ret += len;\n" 624 "len = 0;\n" 625 "}\n", 626 name, have_ellipsis->label, 627 name, have_ellipsis->gen_name, 628 name, have_ellipsis->gen_name, 629 forwstr, 630 name, have_ellipsis->gen_name, 631 name, have_ellipsis->gen_name); 632 } else { 633 fprintf(codefile, 634 "else {\n" 635 "e = ASN1_PARSE_ERROR;\n" 636 "%s;\n" 637 "}\n", 638 forwstr); 639 } 640 break; 641 } 642 case TUTCTime: 643 decode_primitive ("utctime", name, forwstr); 644 break; 645 case TUTF8String: 646 decode_primitive ("utf8string", name, forwstr); 647 break; 648 case TPrintableString: 649 decode_primitive ("printable_string", name, forwstr); 650 break; 651 case TIA5String: 652 decode_primitive ("ia5_string", name, forwstr); 653 break; 654 case TBMPString: 655 decode_primitive ("bmp_string", name, forwstr); 656 break; 657 case TUniversalString: 658 decode_primitive ("universal_string", name, forwstr); 659 break; 660 case TVisibleString: 661 decode_primitive ("visible_string", name, forwstr); 662 break; 663 case TNull: 664 fprintf (codefile, "/* NULL */\n"); 665 break; 666 case TOID: 667 decode_primitive ("oid", name, forwstr); 668 break; 669 default : 670 abort (); 671 } 672 return 0; 673} 674 675void 676generate_type_decode (const Symbol *s) 677{ 678 int preserve = preserve_type(s->name) ? TRUE : FALSE; 679 680 fprintf (codefile, "int ASN1CALL\n" 681 "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE," 682 " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n" 683 "{\n", 684 s->gen_name, s->gen_name); 685 686 switch (s->type->type) { 687 case TInteger: 688 case TBoolean: 689 case TOctetString: 690 case TOID: 691 case TGeneralizedTime: 692 case TGeneralString: 693 case TTeletexString: 694 case TUTF8String: 695 case TPrintableString: 696 case TIA5String: 697 case TBMPString: 698 case TUniversalString: 699 case TVisibleString: 700 case TUTCTime: 701 case TNull: 702 case TEnumerated: 703 case TBitString: 704 case TSequence: 705 case TSequenceOf: 706 case TSet: 707 case TSetOf: 708 case TTag: 709 case TType: 710 case TChoice: 711 fprintf (codefile, 712 "size_t ret = 0;\n" 713 "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n" 714 "int e HEIMDAL_UNUSED_ATTRIBUTE;\n"); 715 if (preserve) 716 fprintf (codefile, "const unsigned char *begin = p;\n"); 717 718 fprintf (codefile, "\n"); 719 fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */ 720 721 decode_type ("data", s->type, 0, "goto fail", "Top", NULL, 1); 722 if (preserve) 723 fprintf (codefile, 724 "data->_save.data = calloc(1, ret);\n" 725 "if (data->_save.data == NULL) { \n" 726 "e = ENOMEM; goto fail; \n" 727 "}\n" 728 "data->_save.length = ret;\n" 729 "memcpy(data->_save.data, begin, ret);\n"); 730 fprintf (codefile, 731 "if(size) *size = ret;\n" 732 "return 0;\n"); 733 fprintf (codefile, 734 "fail:\n" 735 "free_%s(data);\n" 736 "return e;\n", 737 s->gen_name); 738 break; 739 default: 740 abort (); 741 } 742 fprintf (codefile, "}\n\n"); 743} 744