blob: 509a0c28d196a645daa2e28fbe56635509810313 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
Lev Walkin4efbfb72005-02-25 14:20:30 +00002#include "asn1fix.h"
Lev Walkinf15320b2004-06-03 03:38:44 +00003
4/* Print everything to stderr */
5static void _default_error_logger(int _severity, const char *fmt, ...);
6
7/*
8 * Internal check functions.
9 */
Lev Walkind24c62d2004-09-15 11:47:23 +000010static int asn1f_fix_module__phase_1(arg_t *arg);
11static int asn1f_fix_module__phase_2(arg_t *arg);
Lev Walkinf15320b2004-06-03 03:38:44 +000012static int asn1f_fix_simple(arg_t *arg); /* For INTEGER/ENUMERATED */
13static int asn1f_fix_constructed(arg_t *arg); /* For SEQUENCE/SET/CHOICE */
Lev Walkin1ef05162004-08-25 00:42:25 +000014static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */
15static int asn1f_check_constraints(arg_t *arg); /* For subtype constraints */
Lev Walkinf593f102005-02-22 07:59:59 +000016static int asn1f_check_duplicate(arg_t *arg);
Lev Walkin1dec5802005-03-04 09:02:27 +000017static int asn1f_apply_unique_index(arg_t *arg);
Lev Walkinf15320b2004-06-03 03:38:44 +000018
Lev Walkinb45e0672004-08-18 05:42:05 +000019arg_t a1f_replace_me_with_proper_interface_arg;
Lev Walkinf15320b2004-06-03 03:38:44 +000020
21/*
22 * Scan every module defined here in search for inconsistences.
23 */
24int
25asn1f_process(asn1p_t *asn, enum asn1f_flags flags,
26 error_logger_f error_logger) {
27 arg_t arg;
28 int fatals = 0;
29 int warnings = 0;
30
31 /*
32 * Check validity of arguments.
33 */
34 if(asn == NULL) {
35 errno = EINVAL;
36 return -1;
37 }
38
39 /*
40 * If errors handler is not specified, default to internal one.
41 */
42 if(error_logger == 0) {
43 error_logger = _default_error_logger;
44 }
45
46 memset(&arg, 0, sizeof(arg));
47 arg.asn = asn;
48 arg.eh = error_logger;
49
50 if(flags & A1F_DEBUG) {
51 arg.debug = arg.eh;
52 arg.debug(-1, "Called %s() with flags %d", __func__, flags);
53 flags &= ~A1F_DEBUG;
54 }
55
Lev Walkin5253da42004-08-20 13:25:56 +000056 /* Allow SIZE() constraint for INTEGER and other types */
57 if(flags & A1F_EXTENDED_SizeConstraint) {
58 arg.flags |= A1F_EXTENDED_SizeConstraint;
59 flags &= ~A1F_EXTENDED_SizeConstraint;
60 if(arg.debug) {
61 arg.debug(-1,
62 "Extended SizeConstraint support enabled");
63 }
64 }
65
Lev Walkinb45e0672004-08-18 05:42:05 +000066 a1f_replace_me_with_proper_interface_arg = arg;
67
Lev Walkinf15320b2004-06-03 03:38:44 +000068 /*
69 * Check that we haven't missed an unknown flag.
70 */
71 if(flags) {
72 errno = EINVAL;
73 return -1;
74 }
75
76 /*
77 * Process each module in the list.
Lev Walkinf593f102005-02-22 07:59:59 +000078 * PHASE I.
Lev Walkinf15320b2004-06-03 03:38:44 +000079 */
80 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
Lev Walkind24c62d2004-09-15 11:47:23 +000081 int ret = asn1f_fix_module__phase_1(&arg);
Lev Walkinf15320b2004-06-03 03:38:44 +000082 /*
83 * These lines are used for illustration purposes.
84 * RET2RVAL() is used everywhere else.
85 */
86 if(ret == -1) fatals++;
87 if(ret == 1) warnings++;
88 }
Lev Walkinf593f102005-02-22 07:59:59 +000089 /* PHASE II. */
Lev Walkind24c62d2004-09-15 11:47:23 +000090 TQ_FOR(arg.mod, &(asn->modules), mod_next) {
91 int ret = asn1f_fix_module__phase_2(&arg);
92 if(ret == -1) fatals++;
93 if(ret == 1) warnings++;
94 }
95
96 memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));
Lev Walkinf15320b2004-06-03 03:38:44 +000097
98 /*
99 * Compute a return value.
100 */
101 return fatals?-1:warnings?1:0;
102}
103
104/*
105 * Check the internals of a single module.
106 */
107static int
Lev Walkind24c62d2004-09-15 11:47:23 +0000108asn1f_fix_module__phase_1(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000109 asn1p_expr_t *expr;
110 int rvalue = 0;
Lev Walkin1ef05162004-08-25 00:42:25 +0000111 int ret;
Lev Walkinf15320b2004-06-03 03:38:44 +0000112
Lev Walkinb45e0672004-08-18 05:42:05 +0000113 switch((arg->mod->module_flags & MSF_MASK_TAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000114 case MSF_NOFLAGS:
115 case MSF_EXPLICIT_TAGS:
116 case MSF_IMPLICIT_TAGS:
117 case MSF_AUTOMATIC_TAGS:
118 break;
119 default:
120 FATAL("Module %s defined with ambiguous global tagging mode",
121 arg->mod->Identifier);
122 RET2RVAL(-1, rvalue);
123 }
124
Lev Walkinb45e0672004-08-18 05:42:05 +0000125 switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
126 case MSF_NOFLAGS:
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000127 /*
128 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
129 */
Lev Walkinb45e0672004-08-18 05:42:05 +0000130 break;
131 case MSF_unk_INSTRUCTIONS:
132 WARNING("Module %s defined with unrecognized "
133 "encoding reference", arg->mod->Identifier);
134 RET2RVAL(1, rvalue);
135 /* Fall through */
136 case MSF_TAG_INSTRUCTIONS:
137 case MSF_XER_INSTRUCTIONS:
138 break;
139 default:
140 FATAL("Module %s defined with ambiguous encoding reference",
141 arg->mod->Identifier);
142 RET2RVAL(-1, rvalue);
143 }
144
Lev Walkinf15320b2004-06-03 03:38:44 +0000145 /*
146 * Do various non-recursive transformations.
Lev Walkinf15320b2004-06-03 03:38:44 +0000147 */
148 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 arg->expr = expr;
150
Lev Walkinf593f102005-02-22 07:59:59 +0000151 /* Check whether this type is a duplicate */
152 ret = asn1f_check_duplicate(arg);
153 RET2RVAL(ret, rvalue);
154
Lev Walkinf15320b2004-06-03 03:38:44 +0000155 if(expr->meta_type == AMT_PARAMTYPE)
156 /* Do not process the parametrized type just yet */
157 continue;
158
159 DEBUG("=== Now processing \"%s\" at line %d ===",
160 expr->Identifier, expr->_lineno);
161 assert(expr->meta_type != AMT_INVALID);
162
163 /*
164 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).
165 */
166 ret = asn1f_recurse_expr(arg, asn1f_fix_simple);
167 RET2RVAL(ret, rvalue);
168
169 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000170 * 2.5.4
171 */
172 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);
173 RET2RVAL(ret, rvalue);
174
175 /*
Lev Walkind541c252004-09-05 10:36:22 +0000176 * Fix tagging of top-level types.
177 */
178 ret = asn1f_fix_constr_tag(arg, 1);
179 RET2RVAL(ret, rvalue);
180
181 /*
182 * 2.[234] Process SEQUENCE/SET/CHOICE types.
183 */
184 ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);
185 RET2RVAL(ret, rvalue);
186
187 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000188 * 2.5.5
189 */
190 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);
191 RET2RVAL(ret, rvalue);
192
193 /*
194 * Resolve references in constraints.
195 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000196 ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
Lev Walkinf15320b2004-06-03 03:38:44 +0000197 RET2RVAL(ret, rvalue);
198
199 /*
200 * 6. INTEGER value processed at 2.5.4.
201 */
202
203 /*
204 * Make sure everybody's behaving well.
205 */
206 assert(arg->expr == expr);
207 }
208
209 /*
210 * 5. Automatic tagging
211 */
212 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000213
214 arg->expr = expr;
215
216 ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);
217 RET2RVAL(ret, rvalue);
218
219 assert(arg->expr == expr);
220 }
221
222 /*
223 * 8. fix BIT STRING
224 * 9. fix spaces in cstrings
225 */
226 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000227 arg->expr = expr;
228
229 ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);
230 RET2RVAL(ret, rvalue);
231
232 ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);
233 RET2RVAL(ret, rvalue);
234
235 assert(arg->expr == expr);
236 }
237
238 /*
239 * ... Check for tags distinctness.
240 */
241 TQ_FOR(expr, &(arg->mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000242 arg->expr = expr;
243
244 ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);
245 RET2RVAL(ret, rvalue);
246
247 assert(arg->expr == expr);
248 }
249
Lev Walkind24c62d2004-09-15 11:47:23 +0000250 return rvalue;
251}
252
253static int
254asn1f_fix_module__phase_2(arg_t *arg) {
255 asn1p_expr_t *expr;
256 int rvalue = 0;
257 int ret;
258
Lev Walkin1ef05162004-08-25 00:42:25 +0000259 TQ_FOR(expr, &(arg->mod->members), next) {
260 arg->expr = expr;
261
Lev Walkinf593f102005-02-22 07:59:59 +0000262 if(expr->meta_type == AMT_PARAMTYPE)
Lev Walkind541c252004-09-05 10:36:22 +0000263 /* Do not process the parametrized types here */
264 continue;
265
Lev Walkinb25fa062004-09-29 13:17:06 +0000266 /*
Lev Walkin3645c1c2004-10-31 00:11:50 +0000267 * Dereference DEFAULT values.
268 */
269 ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_defaults);
270 RET2RVAL(ret, rvalue);
271
272 /*
Lev Walkinb25fa062004-09-29 13:17:06 +0000273 * Check semantic validity of constraints.
274 */
Lev Walkin1ef05162004-08-25 00:42:25 +0000275 ret = asn1f_recurse_expr(arg, asn1f_check_constraints);
276 RET2RVAL(ret, rvalue);
277
Lev Walkin1dec5802005-03-04 09:02:27 +0000278 /*
279 * Uniquely tag each inner type.
280 */
281 asn1f_apply_unique_index(0);
282 ret = asn1f_recurse_expr(arg, asn1f_apply_unique_index);
283 RET2RVAL(ret, rvalue);
284
Lev Walkin1ef05162004-08-25 00:42:25 +0000285 assert(arg->expr == expr);
286 }
287
Lev Walkinf15320b2004-06-03 03:38:44 +0000288 return rvalue;
289}
290
Lev Walkinf15320b2004-06-03 03:38:44 +0000291static int
292asn1f_fix_simple(arg_t *arg) {
293 int rvalue = 0;
294 int ret;
295
296 ret = asn1f_fix_enum(arg);
297 RET2RVAL(ret, rvalue);
298
299 ret = asn1f_fix_integer(arg);
300 RET2RVAL(ret, rvalue);
301
302 return rvalue;
303}
304
305static int
306asn1f_fix_constructed(arg_t *arg) {
307 int rvalue = 0;
308 int ret;
309
310 switch(arg->expr->expr_type) {
311 case ASN_CONSTR_SEQUENCE:
312 case ASN_CONSTR_SET:
313 case ASN_CONSTR_CHOICE:
314 break;
315 default:
316 return 0;
317 }
318
319 /* Check identifier distinctness */
320 ret = asn1f_check_unique_expr(arg, NULL);
321 RET2RVAL(ret, rvalue);
322
323 /* Fix extensibility */
324 ret = asn1f_fix_constr_ext(arg);
325 RET2RVAL(ret, rvalue);
326
327 /* Fix tagging */
Lev Walkind541c252004-09-05 10:36:22 +0000328 ret = asn1f_fix_constr_tag(arg, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000329 RET2RVAL(ret, rvalue);
330
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000331 /* Import COMPONENTS OF stuff */
332 ret = asn1f_pull_components_of(arg);
333 RET2RVAL(ret, rvalue);
334
Lev Walkinf15320b2004-06-03 03:38:44 +0000335 return rvalue;
336}
337
338static int
Lev Walkin1ef05162004-08-25 00:42:25 +0000339asn1f_resolve_constraints(arg_t *arg) {
Lev Walkinb45e0672004-08-18 05:42:05 +0000340 asn1p_expr_t *top_parent;
Lev Walkin5253da42004-08-20 13:25:56 +0000341 asn1p_expr_type_e etype;
Lev Walkinf15320b2004-06-03 03:38:44 +0000342 int rvalue = 0;
343 int ret;
344
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000345 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkin5253da42004-08-20 13:25:56 +0000346 if(top_parent)
347 etype = top_parent->expr_type;
348 else etype = A1TC_INVALID;
349
Lev Walkin03850182005-03-10 10:02:50 +0000350 DEBUG("(%s)", arg->expr->Identifier);
Lev Walkind541c252004-09-05 10:36:22 +0000351
Lev Walkin4ec3b4c2004-08-22 03:09:24 +0000352 ret = asn1constraint_resolve(arg, arg->expr->module,
353 arg->expr->constraints, etype, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000354 RET2RVAL(ret, rvalue);
Lev Walkinf15320b2004-06-03 03:38:44 +0000355
Lev Walkin1ef05162004-08-25 00:42:25 +0000356 return rvalue;
357}
358
359static int
360asn1f_check_constraints(arg_t *arg) {
361 static enum asn1p_constraint_type_e test_types[] = {
362 ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
363 asn1p_expr_t *top_parent;
364 asn1cnst_range_t *range;
365 asn1p_expr_type_e etype;
366 unsigned int i;
367 int rvalue = 0;
368 int ret;
369
Lev Walkin03850182005-03-10 10:02:50 +0000370 DEBUG("(%s{%d/%d})",
Lev Walkind541c252004-09-05 10:36:22 +0000371 arg->expr->Identifier,
372 arg->expr->meta_type, arg->expr->expr_type);
373
Lev Walkin1ef05162004-08-25 00:42:25 +0000374 top_parent = asn1f_find_terminal_type(arg, arg->expr);
375 if(!top_parent)
376 return 0;
377 etype = top_parent->expr_type;
378
Lev Walkinb45e0672004-08-18 05:42:05 +0000379 ret = asn1constraint_pullup(arg);
380 RET2RVAL(ret, rvalue);
381
Lev Walkin1ef05162004-08-25 00:42:25 +0000382 for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {
383 range = asn1constraint_compute_PER_range(
Lev Walkinb9fa7802004-08-25 02:04:39 +0000384 etype,
Lev Walkin1ef05162004-08-25 00:42:25 +0000385 arg->expr->combined_constraints,
Lev Walkinb9fa7802004-08-25 02:04:39 +0000386 test_types[i], 0, 0, 0);
Lev Walkind541c252004-09-05 10:36:22 +0000387 if(!range && errno == EPERM) {
388 FATAL("This error happened for %s (%d) at line %d",
389 arg->expr->Identifier,
390 arg->expr->meta_type,
391 arg->expr->_lineno);
Lev Walkin1ef05162004-08-25 00:42:25 +0000392 return -1;
Lev Walkind541c252004-09-05 10:36:22 +0000393 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000394 asn1constraint_range_free(range);
Lev Walkinb45e0672004-08-18 05:42:05 +0000395 }
Lev Walkin1ef05162004-08-25 00:42:25 +0000396
Lev Walkinf15320b2004-06-03 03:38:44 +0000397 return rvalue;
398}
399
Lev Walkinf593f102005-02-22 07:59:59 +0000400static int
401asn1f_check_duplicate(arg_t *arg) {
402 arg_t tmparg = *arg;
403
404 /*
405 * This is a linear scan in search of a similar type.
406 * The linear scan is just fine for the task, no need to over-optimize.
407 */
408 TQ_FOR(tmparg.mod, &arg->asn->modules, mod_next) {
409 TQ_FOR(tmparg.expr, &(tmparg.mod->members), next) {
410 assert(tmparg.expr->Identifier);
411 assert(arg->expr->Identifier);
412 if(tmparg.expr == arg->expr) break;
413
414 if(strcmp(tmparg.expr->Identifier,
415 arg->expr->Identifier) == 0) {
416 int diff_files = strcmp(arg->mod->source_file_name, tmparg.mod->source_file_name) ? 1 : 0;
417 FATAL("ASN.1 expression \"%s\" at line %d of module %s\n"
418 "clashes with expression \"%s\" at line %d of module %s"
419 "%s%s%s.\n"
420 "Please rename either instance to resolve the conflict",
421 arg->expr->Identifier,
422 arg->expr->_lineno,
423 arg->mod->Identifier,
424 tmparg.expr->Identifier,
425 tmparg.expr->_lineno,
426 tmparg.mod->Identifier,
427 diff_files ? " (" : "",
428 diff_files ? tmparg.mod->source_file_name : "",
429 diff_files ? ")" : ""
430 );
431 return -1;
432 }
433 }
434 if(tmparg.mod == arg->mod) break;
435 }
436
437 return 0;
438}
439
Lev Walkin1dec5802005-03-04 09:02:27 +0000440static int
441asn1f_apply_unique_index(arg_t *arg) {
442 static int unique_index;
443 if(!arg) { unique_index = 0; return 0; }
444
Lev Walkin1dec5802005-03-04 09:02:27 +0000445 arg->expr->_type_unique_index = ++unique_index;
446
447 return 0;
448}
449
Lev Walkinf15320b2004-06-03 03:38:44 +0000450/*
451 * Print everything to stderr
452 */
453static void
454_default_error_logger(int _severity, const char *fmt, ...) {
455 va_list ap;
456 char *pfx = "";
457
458 switch(_severity) {
459 case -1: pfx = "DEBUG: "; break;
460 case 0: pfx = "WARNING: "; break;
461 case 1: pfx = "FATAL: "; break;
462 }
463
464 fprintf(stderr, "%s", pfx);
465 va_start(ap, fmt);
466 vfprintf(stderr, fmt, ap);
467 va_end(ap);
468 fprintf(stderr, "\n");
469}