blob: 19e8bad418b3e4e8301225f22a68fb64d92f7ebf [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
4static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
Lev Walkind541c252004-09-05 10:36:22 +00005static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinf15320b2004-06-03 03:38:44 +00006
Lev Walkin4ec3b4c2004-08-22 03:09:24 +00007int
8asn1f_pull_components_of(arg_t *arg) {
9 TQ_HEAD(asn1p_expr_t) list;
10 asn1p_expr_t *expr = arg->expr;
11 asn1p_expr_t *memb;
12 int r_value = 0;
13
14 switch(expr->expr_type) {
15 case ASN_CONSTR_SEQUENCE:
16 case ASN_CONSTR_SET:
17 break;
18 default:
19 return 0;
20 }
21
22 TQ_INIT(&list);
23
24 /*
25 * Look into
26 */
27 while((memb = TQ_REMOVE(&(expr->members), next))) {
28 asn1p_expr_t *coft; /* COMPONENTS OF thing itself */
29 asn1p_expr_t *terminal; /* Terminal of the referenced type */
30
31 if(memb->expr_type != A1TC_COMPONENTS_OF) {
32 TQ_ADD(&list, memb, next);
33 continue;
34 }
35
36 coft = TQ_FIRST(&memb->members);
37 assert(coft);
38 assert(!TQ_NEXT(coft, next));
39
40 /*
41 * Find the referenced type.
42 */
43 terminal = asn1f_find_terminal_type(arg, coft);
44 if(!terminal || (terminal->expr_type != expr->expr_type)) {
45 FATAL("COMPONENTS OF at line %d "
46 "must reference a %s type",
47 coft->_lineno,
48 expr->expr_type==ASN_CONSTR_SET
49 ? "SET" : "SEQUENCE"
50 );
51 TQ_ADD(&list, memb, next);
52 r_value = -1;
53 continue;
54 }
55
56 /*
57 * Clone the final structure.
58 */
59
60 coft = asn1p_expr_clone(terminal, 1 /* Skip extensions */);
61 if(!coft) return -1; /* ENOMEM */
62
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +080063 if(1) {
Lev Walkin75d76b42005-04-13 13:20:20 +000064 asn1p_expr_free(memb); /* Don't need it anymore*/
65 } else {
66 /* Actual removal clashes with constraints... skip. */
67 }
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000068
69 /*
70 * Move all components of the cloned structure
71 * into the current one.
72 */
Lev Walkin1004aa92004-09-08 00:28:11 +000073 while((memb = TQ_REMOVE(&(coft->members), next))) {
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000074 TQ_ADD(&list, memb, next);
Lev Walkin1004aa92004-09-08 00:28:11 +000075 memb->parent_expr = expr;
76 }
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000077
78 asn1p_expr_free(coft); /* Remove wrapper */
79 }
80
81 /* Move the stuff back */
Lev Walkin1ef05162004-08-25 00:42:25 +000082 TQ_MOVE(&(expr->members), &list);
Lev Walkin4ec3b4c2004-08-22 03:09:24 +000083
84 return r_value;
85}
Lev Walkinf15320b2004-06-03 03:38:44 +000086
Lev Walkind541c252004-09-05 10:36:22 +000087/*
88 * Fix extensibility parts inside constructed types (SEQUENCE, SET, CHOICE).
89 */
Lev Walkinf15320b2004-06-03 03:38:44 +000090int
91asn1f_fix_constr_ext(arg_t *arg) {
92 asn1p_expr_t *expr = arg->expr;
93 asn1p_expr_t *v;
94 TQ_HEAD(asn1p_expr_t) root_list;
95 TQ_HEAD(asn1p_expr_t) ext_list;
96 TQ_HEAD(asn1p_expr_t) *cur_list;
97 int r_value = 0;
98 int ext_count = 0;
99
100 switch(expr->expr_type) {
101 case ASN_CONSTR_SEQUENCE:
102 case ASN_CONSTR_SET:
103 case ASN_CONSTR_CHOICE:
104 break;
105 default:
106 return 0;
107 }
108
Lev Walkin03850182005-03-10 10:02:50 +0000109 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000110
111 TQ_INIT(&root_list);
112 TQ_INIT(&ext_list);
113 cur_list = (void *)&root_list;
114
Lev Walkind541c252004-09-05 10:36:22 +0000115 /*
116 * Split the set of fields into two lists, the root list
117 * and the extensions list.
118 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000119 while((v = TQ_REMOVE(&(expr->members), next))) {
120 if(v->expr_type == A1TC_EXTENSIBLE) {
121 ext_count++;
122 switch(ext_count) {
123 case 1: cur_list = (void *)&ext_list; break;
124 case 2:
125 cur_list = (void *)&root_list;
126 if(v->value) {
127 FATAL("Optional extension marker "
128 "must not contain "
129 "an exception mark "
130 "at line %d", v->_lineno);
131 r_value = -1;
132 }
133 asn1p_expr_free(v);
134 continue;
135 case 3:
136 FATAL("Third extension marker "
137 "is not allowed at line %d", v->_lineno);
138 default:
139 r_value = -1;
140 }
141 }
142
143 TQ_ADD(cur_list, v, next);
144 }
145
146 /*
147 * Copy the root list and extension list back into the main list.
148 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000149 TQ_MOVE(&(expr->members), &root_list);
Lev Walkinf15320b2004-06-03 03:38:44 +0000150 while((v = TQ_REMOVE(&ext_list, next)))
151 TQ_ADD(&(expr->members), v, next);
152
153 if(arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED
Lev Walkin1ef05162004-08-25 00:42:25 +0000154 && ext_count == 0) {
Lev Walkina9532f42006-09-17 04:52:50 +0000155 v = asn1p_expr_new(0, arg->mod);
Lev Walkinf15320b2004-06-03 03:38:44 +0000156 if(v) {
157 v->Identifier = strdup("...");
158 v->expr_type = A1TC_EXTENSIBLE;
159 v->meta_type = AMT_TYPE;
Lev Walkin7ccf2a42004-07-01 00:51:31 +0000160 v->_lineno = expr->_lineno; /* The best we can do */
Lev Walkinf15320b2004-06-03 03:38:44 +0000161 if(v->Identifier == NULL) {
162 asn1p_expr_free(v);
163 r_value = -1;
164 } else {
Lev Walkin1004aa92004-09-08 00:28:11 +0000165 asn1p_expr_add(expr, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000166 }
167 } else {
168 r_value = -1;
169 }
170 }
171
172 return r_value;
173}
174
175
176int
Lev Walkind541c252004-09-05 10:36:22 +0000177asn1f_fix_constr_tag(arg_t *arg, int fix_top_level) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000178 asn1p_expr_t *expr = arg->expr;
179 asn1p_expr_t *v;
Lev Walkinf15320b2004-06-03 03:38:44 +0000180 int root_tagged = 0; /* The root component is manually tagged */
181 int ext_tagged = 0; /* The extensions are manually tagged */
182 int component_number = 0;
183 int r_value = 0;
184
Lev Walkin03850182005-03-10 10:02:50 +0000185 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
Lev Walkind541c252004-09-05 10:36:22 +0000186
187 /*
188 * Fix the top-level type itself first.
189 */
190 if(fix_top_level) {
191 if(expr->tag.tag_class == TC_NOCLASS)
192 return r_value;
193
194 if(_asn1f_fix_type_tag(arg, expr))
195 r_value = -1;
196
197 return r_value;
198 }
199
Lev Walkinf15320b2004-06-03 03:38:44 +0000200 switch(expr->expr_type) {
201 case ASN_CONSTR_SEQUENCE:
202 case ASN_CONSTR_SET:
203 case ASN_CONSTR_CHOICE:
204 break;
205 default:
206 return 0;
207 }
208
Lev Walkinf15320b2004-06-03 03:38:44 +0000209 TQ_FOR(v, &(expr->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000210
211 if(v->expr_type == A1TC_EXTENSIBLE) {
212 component_number++;
213 continue;
214 }
215
216 if(v->tag.tag_class == TC_NOCLASS) {
217 continue;
Lev Walkinf15320b2004-06-03 03:38:44 +0000218 }
219
Lev Walkind541c252004-09-05 10:36:22 +0000220 switch(component_number) {
221 case 0: case 2:
222 root_tagged = 1; break;
223 default:
224 ext_tagged = 1; break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000225 }
226
Lev Walkind541c252004-09-05 10:36:22 +0000227 if(_asn1f_fix_type_tag(arg, v))
228 r_value = -1;
229
Lev Walkinf15320b2004-06-03 03:38:44 +0000230 }
231
Lev Walkind43915b2004-09-15 11:48:34 +0000232 if((arg->mod->module_flags & MSF_AUTOMATIC_TAGS)
233 && !root_tagged) {
234 if(ext_tagged) {
235 /* X.690: 28.4 */
236 FATAL("In %s at line %d: "
237 "extensions are tagged "
238 "but root components are not",
239 expr->Identifier, expr->_lineno);
240 r_value = -1;
241 } else {
242 /* Make a decision on automatic tagging */
243 expr->auto_tags_OK = 1;
244 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000245 }
246
247 return r_value;
248}
249
Lev Walkind541c252004-09-05 10:36:22 +0000250static int
251_asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr) {
252 int must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, expr);
Lev Walkine54e9422005-07-21 01:18:19 +0000253 int module_impl_tags = (arg->mod->module_flags
254 & (MSF_IMPLICIT_TAGS | MSF_AUTOMATIC_TAGS));
Lev Walkind541c252004-09-05 10:36:22 +0000255 int r_value = 0;
256
Lev Walkin07f388c2004-10-11 11:43:08 +0000257 if(expr->tag.tag_mode == TM_DEFAULT) {
258 if(must_explicit || module_impl_tags == 0)
Lev Walkind541c252004-09-05 10:36:22 +0000259 expr->tag.tag_mode = TM_EXPLICIT;
Lev Walkin07f388c2004-10-11 11:43:08 +0000260 else
261 expr->tag.tag_mode = TM_IMPLICIT;
Lev Walkind541c252004-09-05 10:36:22 +0000262 }
263
264 /*
265 * Perform a final sanity check.
266 */
267 if(must_explicit) {
268 if(expr->tag.tag_mode == TM_IMPLICIT) {
269 FATAL("%s tagged in IMPLICIT mode "
270 "but must be EXPLICIT at line %d",
271 expr->Identifier, expr->_lineno);
272 r_value = -1;
273 } else {
274 expr->tag.tag_mode = TM_EXPLICIT;
275 }
276 }
277
278 return r_value;
279}
280
Lev Walkinf15320b2004-06-03 03:38:44 +0000281int
282asn1f_fix_constr_autotag(arg_t *arg) {
283 asn1p_expr_t *expr = arg->expr;
284 asn1p_expr_t *v;
Lev Walkinb8108ec2004-09-29 13:17:17 +0000285 asn1c_integer_t tag_value = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000286 int r_value = 0;
287
288 switch(expr->expr_type) {
289 case ASN_CONSTR_SEQUENCE:
290 case ASN_CONSTR_SET:
291 case ASN_CONSTR_CHOICE:
292 if(expr->auto_tags_OK)
293 break;
294 /* Automatic tagging is not applicable */
295 /* Fall through */
296 default:
297 return 0;
298 }
299
Lev Walkin03850182005-03-10 10:02:50 +0000300 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000301
302 TQ_FOR(v, &(expr->members), next) {
303 int must_explicit;
304
Lev Walkin144db9b2004-10-12 23:26:53 +0000305 if(v->expr_type == A1TC_EXTENSIBLE) {
306 /* 28.5, d) */
307 continue;
308 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000309
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000310 if(0) {
311 /* This may be not true in case COMPONENTS OF */
312 assert(v->tag.tag_class == TC_NOCLASS);
313 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000314
315 must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
316
317 v->tag.tag_class = TC_CONTEXT_SPECIFIC;
318 v->tag.tag_mode = must_explicit ? TM_EXPLICIT : TM_IMPLICIT;
319 v->tag.tag_value = tag_value++;
320 }
321
322 return r_value;
323}
324
325/*
326 * Check that tags are distinct.
327 */
328int
329asn1f_check_constr_tags_distinct(arg_t *arg) {
330 asn1p_expr_t *expr = arg->expr;
331 asn1p_expr_t *v;
332 int r_value = 0;
333
334 switch(expr->expr_type) {
335 case ASN_CONSTR_SEQUENCE:
336 case ASN_CONSTR_SET:
337 case ASN_CONSTR_CHOICE:
338 break;
339 default:
340 return 0;
341 }
342
343 TQ_FOR(v, &(expr->members), next) {
344 /*
345 * In every series of non-mandatory components,
346 * the tags must be distinct from each other AND the
347 * tag of the following mandatory component.
348 * For SET and CHOICE treat everything as a big set of
349 * non-mandatory components.
350 */
Lev Walkind43915b2004-09-15 11:48:34 +0000351 if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker.flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000352 asn1p_expr_t *nv;
353 for(nv = v; (nv = TQ_NEXT(nv, next));) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000354 DEBUG("S/C comparing tags %s s. %s",
355 v->Identifier, nv->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000356 if(_asn1f_compare_tags(arg, v, nv))
357 r_value = -1;
358 if(expr->expr_type == ASN_CONSTR_SEQUENCE
Lev Walkind43915b2004-09-15 11:48:34 +0000359 && !nv->marker.flags) break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000360 }
361 }
362 }
363
364 return r_value;
365}
366
367static int
368_asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
Lev Walkind541c252004-09-05 10:36:22 +0000369 struct asn1p_type_tag_s tag;
370 struct asn1p_type_tag_s save_tag;
Lev Walkinf15320b2004-06-03 03:38:44 +0000371 asn1p_expr_t *reft;
Lev Walkind541c252004-09-05 10:36:22 +0000372 int ret;
373
374 /*
375 * Fetch the _next_ tag for this type.
376 */
377 save_tag = v->tag; /* Save existing tag */
378 memset(&v->tag, 0, sizeof(v->tag)); /* Remove it temporarily */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700379 ret = asn1f_fetch_outmost_tag(arg->asn, arg->ns, arg->mod, v, &tag, 0);
Lev Walkind541c252004-09-05 10:36:22 +0000380 v->tag = save_tag; /* Restore the tag back */
381
382 if(ret == 0) return 0; /* If found tag, it's okay */
Lev Walkinf15320b2004-06-03 03:38:44 +0000383
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000384 reft = asn1f_find_terminal_type(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000385 if(reft) {
386 switch(reft->expr_type) {
Lev Walkind541c252004-09-05 10:36:22 +0000387 case ASN_TYPE_ANY:
Lev Walkinf15320b2004-06-03 03:38:44 +0000388 case ASN_CONSTR_CHOICE:
389 return 1;
390 default:
391 return 0;
392 }
393 }
394
395 return 0;
396}
397
398/*
399 * Check that the tags are distinct.
400 */
401static int
402_asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
403 struct asn1p_type_tag_s ta, tb;
404 int ra, rb;
405 int ret;
406
Lev Walkinc0e03b92017-08-22 01:48:23 -0700407 ra = asn1f_fetch_outmost_tag(arg->asn, arg->ns, arg->mod, a,
Lev Walkin59b176e2005-11-26 11:25:14 +0000408 &ta, AFT_IMAGINARY_ANY);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700409 rb = asn1f_fetch_outmost_tag(arg->asn, arg->ns, arg->mod, b,
Lev Walkin59b176e2005-11-26 11:25:14 +0000410 &tb, AFT_IMAGINARY_ANY);
Lev Walkinf15320b2004-06-03 03:38:44 +0000411
412 /*
413 * If both tags are explicitly or implicitly given, use them.
414 */
Lev Walkin59b176e2005-11-26 11:25:14 +0000415 DEBUG("Fetching outmost tags: %d, %d", ra, rb);
Lev Walkinf15320b2004-06-03 03:38:44 +0000416 if(ra == 0 && rb == 0) {
417 /*
418 * Simple case: fetched both tags.
419 */
Lev Walkind541c252004-09-05 10:36:22 +0000420
421 if((ta.tag_value == tb.tag_value
422 && ta.tag_class == tb.tag_class)
423 || ta.tag_value == -1 /* Spread IMAGINARY ANY tag... */
424 || tb.tag_value == -1 /* ...it is an evil virus, fear it! */
425 ) {
Lev Walkin71160962005-06-02 05:21:53 +0000426 char tagbuf[2][TAG2STRING_BUFFER_SIZE];
Lev Walkinf15320b2004-06-03 03:38:44 +0000427 char *p = (a->expr_type == A1TC_EXTENSIBLE)
428 ?"potentially ":"";
Lev Walkind43915b2004-09-15 11:48:34 +0000429 FATAL("Processing %s at line %d: component \"%s\" at line %d %shas the same tag "
Lev Walkin7bb4ad02008-01-01 20:04:52 +0000430 "as component \"%s\" at line %d",
Lev Walkind43915b2004-09-15 11:48:34 +0000431 arg->expr->Identifier,
432 arg->expr->_lineno,
Lev Walkinf15320b2004-06-03 03:38:44 +0000433 a->Identifier,
434 a->_lineno,
435 p,
436 b->Identifier,
437 b->_lineno
438 );
Lev Walkin725883b2006-10-09 12:07:58 +0000439 FATAL("Consider adding AUTOMATIC TAGS "
440 "after module %s DEFINITIONS, "
441 "or manually tag components",
442 arg->expr->module->ModuleName);
Lev Walkin71160962005-06-02 05:21:53 +0000443 DEBUG("Tags: %s %s vs. %s %s",
444 asn1p_tag2string(&ta, tagbuf[0]),
445 a->Identifier,
446 asn1p_tag2string(&tb, tagbuf[1]),
447 b->Identifier
448 );
Lev Walkin7ccf2a42004-07-01 00:51:31 +0000449 if((arg->mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
450 && (a->expr_type == A1TC_EXTENSIBLE)
451 && (b->expr_type == A1TC_EXTENSIBLE)) {
452 FATAL("The previous error is due to "
453 "improper use of "
454 "EXTENSIBILITY IMPLIED flag "
455 "of module %s",
Lev Walkinb36317c2005-08-12 10:09:10 +0000456 arg->mod->ModuleName);
Lev Walkin7ccf2a42004-07-01 00:51:31 +0000457 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000458 return -1;
459 } else {
460 /* Tags are distinct */
461 return 0;
462 }
463 }
464
465 /**********************************************************
466 * Now we must perform some very funny recursion to check
467 * multiple components of CHOICE type, etc.
468 */
469
470 DEBUG("Comparing tags %s:%x <-> %s:%x",
471 a->Identifier, a->expr_type,
472 b->Identifier, b->expr_type);
473
Lev Walkind43915b2004-09-15 11:48:34 +0000474 if(ra && a->meta_type == AMT_TYPEREF) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000475
476 DEBUG(" %s is a type reference", a->Identifier);
477
Lev Walkinc0e03b92017-08-22 01:48:23 -0700478 a = asn1f_lookup_symbol(arg, a->rhs_pspecs, a->reference);
479 if(!a) return 0; /* Already FATAL()'ed somewhere else */
480 return WITH_MODULE(a->module, _asn1f_compare_tags(arg, a, b));
481 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000482
Lev Walkind43915b2004-09-15 11:48:34 +0000483 if(ra && a->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000484 asn1p_expr_t *v;
485
486 DEBUG(" %s is a choice type (%d)", a->Identifier, a->_mark);
487
488 /*
489 * Iterate over members of CHOICE.
490 */
491 //if(a->_mark & TM_RECURSION) return 0;
492 TQ_FOR(v, &(a->members), next) {
493 //a->_mark |= TM_RECURSION;
494 ret = _asn1f_compare_tags(arg, v, b);
495 //a->_mark &= ~TM_RECURSION;
496 if(ret) return ret;
497 }
498 return 0;
499 }
500
Lev Walkind43915b2004-09-15 11:48:34 +0000501 if(rb && b->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000502 return _asn1f_compare_tags(arg, b, a);
503 }
504
505 if(a->_mark & TM_RECURSION) return 0;
506 if(b->_mark & TM_RECURSION) return 0;
507 a->_mark |= TM_RECURSION;
508 b->_mark |= TM_RECURSION;
509 ret = _asn1f_compare_tags(arg, b, a);
510 a->_mark &= ~TM_RECURSION;
511 b->_mark &= ~TM_RECURSION;
512
513 return ret;
514}
515