s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / source4 / heimdal / lib / asn1 / gen_copy.c
1 /*
2  * Copyright (c) 1997 - 2005 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
36 RCSID("$Id$");
37
38 static int used_fail;
39
40 static void
41 copy_primitive (const char *typename, const char *from, const char *to)
42 {
43     fprintf (codefile, "if(der_copy_%s(%s, %s)) goto fail;\n",
44              typename, from, to);
45     used_fail++;
46 }
47
48 static void
49 copy_type (const char *from, const char *to, const Type *t, int preserve)
50 {
51     switch (t->type) {
52     case TType:
53 #if 0
54         copy_type (from, to, t->symbol->type, preserve);
55 #endif
56         fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n",
57                  t->symbol->gen_name, from, to);
58         used_fail++;
59         break;
60     case TInteger:
61         if (t->range == NULL && t->members == NULL) {
62             copy_primitive ("heim_integer", from, to);
63             break;
64         }
65         /* FALLTHROUGH */
66     case TBoolean:
67     case TEnumerated :
68         fprintf(codefile, "*(%s) = *(%s);\n", to, from);
69         break;
70     case TOctetString:
71         copy_primitive ("octet_string", from, to);
72         break;
73     case TBitString:
74         if (HEIM_TAILQ_EMPTY(t->members))
75             copy_primitive ("bit_string", from, to);
76         else
77             fprintf(codefile, "*(%s) = *(%s);\n", to, from);
78         break;
79     case TSet:
80     case TSequence:
81     case TChoice: {
82         Member *m, *have_ellipsis = NULL;
83
84         if(t->members == NULL)
85             break;
86
87         if ((t->type == TSequence || t->type == TChoice) && preserve) {
88             fprintf(codefile,
89                     "{ int ret;\n"
90                     "ret = der_copy_octet_string(&(%s)->_save, &(%s)->_save);\n"
91                     "if (ret) goto fail;\n"
92                     "}\n",
93                     from, to);
94             used_fail++;
95         }
96
97         if(t->type == TChoice) {
98             fprintf(codefile, "(%s)->element = (%s)->element;\n", to, from);
99             fprintf(codefile, "switch((%s)->element) {\n", from);
100         }
101
102         HEIM_TAILQ_FOREACH(m, t->members, members) {
103             char *fs;
104             char *ts;
105
106             if (m->ellipsis) {
107                 have_ellipsis = m;
108                 continue;
109             }
110
111             if(t->type == TChoice)
112                 fprintf(codefile, "case %s:\n", m->label);
113
114             if (asprintf (&fs, "%s(%s)->%s%s",
115                           m->optional ? "" : "&", from,
116                           t->type == TChoice ? "u." : "", m->gen_name) < 0)
117                 errx(1, "malloc");
118             if (fs == NULL)
119                 errx(1, "malloc");
120             if (asprintf (&ts, "%s(%s)->%s%s",
121                           m->optional ? "" : "&", to,
122                           t->type == TChoice ? "u." : "", m->gen_name) < 0)
123                 errx(1, "malloc");
124             if (ts == NULL)
125                 errx(1, "malloc");
126             if(m->optional){
127                 fprintf(codefile, "if(%s) {\n", fs);
128                 fprintf(codefile, "%s = malloc(sizeof(*%s));\n", ts, ts);
129                 fprintf(codefile, "if(%s == NULL) goto fail;\n", ts);
130                 used_fail++;
131             }
132             copy_type (fs, ts, m->type, FALSE);
133             if(m->optional){
134                 fprintf(codefile, "}else\n");
135                 fprintf(codefile, "%s = NULL;\n", ts);
136             }
137             free (fs);
138             free (ts);
139             if(t->type == TChoice)
140                 fprintf(codefile, "break;\n");
141         }
142         if(t->type == TChoice) {
143             if (have_ellipsis) {
144                 fprintf(codefile, "case %s: {\n"
145                         "int ret;\n"
146                         "ret=der_copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n"
147                         "if (ret) goto fail;\n"
148                         "break;\n"
149                         "}\n",
150                         have_ellipsis->label,
151                         from, have_ellipsis->gen_name,
152                         to, have_ellipsis->gen_name);
153                 used_fail++;
154             }
155             fprintf(codefile, "}\n");
156         }
157         break;
158     }
159     case TSetOf:
160     case TSequenceOf: {
161         char *f = NULL, *T = NULL;
162
163         fprintf (codefile, "if(((%s)->val = "
164                  "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
165                  to, from, to, from);
166         fprintf (codefile, "goto fail;\n");
167         used_fail++;
168         fprintf(codefile,
169                 "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n",
170                 to, to, from, to);
171         if (asprintf(&f, "&(%s)->val[(%s)->len]", from, to) < 0)
172             errx(1, "malloc");
173         if (f == NULL)
174             errx(1, "malloc");
175         if (asprintf(&T, "&(%s)->val[(%s)->len]", to, to) < 0)
176             errx(1, "malloc");
177         if (T == NULL)
178             errx(1, "malloc");
179         copy_type(f, T, t->subtype, FALSE);
180         fprintf(codefile, "}\n");
181         free(f);
182         free(T);
183         break;
184     }
185     case TGeneralizedTime:
186         fprintf(codefile, "*(%s) = *(%s);\n", to, from);
187         break;
188     case TGeneralString:
189         copy_primitive ("general_string", from, to);
190         break;
191     case TTeletexString:
192         copy_primitive ("general_string", from, to);
193         break;
194     case TUTCTime:
195         fprintf(codefile, "*(%s) = *(%s);\n", to, from);
196         break;
197     case TUTF8String:
198         copy_primitive ("utf8string", from, to);
199         break;
200     case TPrintableString:
201         copy_primitive ("printable_string", from, to);
202         break;
203     case TIA5String:
204         copy_primitive ("ia5_string", from, to);
205         break;
206     case TBMPString:
207         copy_primitive ("bmp_string", from, to);
208         break;
209     case TUniversalString:
210         copy_primitive ("universal_string", from, to);
211         break;
212     case TVisibleString:
213         copy_primitive ("visible_string", from, to);
214         break;
215     case TTag:
216         copy_type (from, to, t->subtype, preserve);
217         break;
218     case TOID:
219         copy_primitive ("oid", from, to);
220         break;
221     case TNull:
222         break;
223     default :
224         abort ();
225     }
226 }
227
228 void
229 generate_type_copy (const Symbol *s)
230 {
231   int preserve = preserve_type(s->name) ? TRUE : FALSE;
232   int save_used_fail = used_fail;
233   int deco_opt;
234   char *ft, *fn;
235
236   used_fail = 0;
237
238   fprintf (codefile, "int ASN1CALL\n"
239            "copy_%s(const %s *from, %s *to)\n"
240            "{\n"
241            "memset(to, 0, sizeof(*to));\n",
242            s->gen_name, s->gen_name, s->gen_name);
243   copy_type ("from", "to", s->type, preserve);
244   if (decorate_type(s->gen_name, &ft, &fn, &deco_opt)) {
245       if (deco_opt) {
246           fprintf(codefile, "if (from->%s) {\n", fn);
247           fprintf(codefile, "(to)->%s = malloc(sizeof(*(to)->%s));\n", fn, fn);
248           fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", ft, fn, fn);
249           fprintf(codefile, "}\n");
250       } else {
251           fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", ft, fn, fn);
252       }
253       used_fail++;
254       free(ft);
255       free(fn);
256   }
257   fprintf (codefile, "return 0;\n");
258
259   if (used_fail)
260       fprintf (codefile, "fail:\n"
261                "free_%s(to);\n"
262                "return ENOMEM;\n",
263                s->gen_name);
264
265   fprintf(codefile,
266           "}\n\n");
267   used_fail = save_used_fail;
268 }
269