blob: cf29a336a32ff00187bd54b9edb57e18017042b4 [file] [log] [blame]
Lev Walkin4efbfb72005-02-25 14:20:30 +00001#include "asn1fix_internal.h"
2#include "asn1fix_constraint.h"
3#include "asn1fix_crange.h"
Lev Walkinb45e0672004-08-18 05:42:05 +00004
Lev Walkin38d00172006-09-21 02:21:53 +00005static void _remove_extensions(arg_t *arg, asn1p_constraint_t *ct, int flast);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +00006static int constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08007static int constraint_object_resolve(arg_t *arg, asn1p_value_t *value);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +00008static int constraint_value_resolve(arg_t *arg, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype);
Lev Walkinb45e0672004-08-18 05:42:05 +00009
10int
11asn1constraint_pullup(arg_t *arg) {
12 asn1p_expr_t *expr = arg->expr;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +000013 asn1p_expr_t *top_parent;
Lev Walkinb45e0672004-08-18 05:42:05 +000014 asn1p_constraint_t *ct_parent;
15 asn1p_constraint_t *ct_expr;
16 int ret;
17
18 if(expr->combined_constraints)
19 return 0; /* Operation already performed earlier */
20
21 switch(expr->meta_type) {
22 case AMT_TYPE:
23 case AMT_TYPEREF:
Bi-Ruei, Chiu50934ba2017-09-11 08:50:59 +080024 case AMT_VALUESET:
Lev Walkinb45e0672004-08-18 05:42:05 +000025 break;
26 default:
27 return 0; /* Nothing to do */
28 }
29
30 if(expr->expr_type == A1TC_REFERENCE) {
31 asn1p_ref_t *ref = expr->reference;
Lev Walkinb45e0672004-08-18 05:42:05 +000032 asn1p_expr_t *parent_expr;
33
34 assert(ref);
Lev Walkinc0e03b92017-08-22 01:48:23 -070035 parent_expr = asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref);
36 if(!parent_expr) {
Lev Walkinb45e0672004-08-18 05:42:05 +000037 if(errno != EEXIST) {
38 DEBUG("\tWhile fetching parent constraints: "
39 "type \"%s\" not found: %s",
40 asn1f_printable_reference(ref),
41 strerror(errno));
42 return -1;
43 } else {
44 /*
45 * -fknown-extern-type is given.
46 * Assume there are no constraints there.
47 */
48 WARNING("External type \"%s\": "
49 "assuming no constraints",
50 asn1f_printable_reference(ref));
51 ct_parent = 0;
52 }
53 } else {
54 arg->expr = parent_expr;
55 ret = asn1constraint_pullup(arg);
56 arg->expr = expr;
57 if(ret) return ret;
58
59 ct_parent = parent_expr->combined_constraints;
60 }
Lev Walkinc0e03b92017-08-22 01:48:23 -070061 } else {
Lev Walkinb45e0672004-08-18 05:42:05 +000062 ct_parent = 0;
63 }
64
65 ct_expr = expr->constraints;
66
67 if(!ct_parent && !ct_expr)
68 return 0; /* No constraints to consider */
69
Lev Walkin7ec9b4c2005-03-20 12:57:21 +000070 /*
71 * Resolve constraints, if not already resolved.
72 */
73 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkinc0e03b92017-08-22 01:48:23 -070074 ret = asn1constraint_resolve(
75 arg, ct_expr, top_parent ? top_parent->expr_type : A1TC_INVALID, 0);
76 if(ret) return ret;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +000077
78 /*
79 * Copy parent type constraints.
80 */
Lev Walkinb45e0672004-08-18 05:42:05 +000081 if(ct_parent) {
82 ct_parent = asn1p_constraint_clone(ct_parent);
83 assert(ct_parent);
84 }
85
86 /*
87 * If the current type does not have constraints, it inherits
88 * the constraints of a parent.
89 */
90 if(ct_parent && !ct_expr) {
91 expr->combined_constraints = ct_parent;
92 return 0;
93 }
94
95 ct_expr = asn1p_constraint_clone(ct_expr);
96 assert(ct_expr);
97
98 /*
99 * Now we have a set of current expression's constraints,
100 * and an optional set of the parent expression's constraints.
101 */
102
103 if(ct_parent) {
104 /*
105 * If we have a parent, remove all the extensions (46.4).
106 */
Lev Walkin38d00172006-09-21 02:21:53 +0000107 _remove_extensions(arg, ct_parent, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000108
109 expr->combined_constraints = ct_parent;
110 if(ct_expr->type == ACT_CA_SET) {
Lev Walkind541c252004-09-05 10:36:22 +0000111 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +0000112 for(i = 0; i < ct_expr->el_count; i++) {
113 if(asn1p_constraint_insert(
114 expr->combined_constraints,
115 ct_expr->elements[i])) {
116 expr->combined_constraints = 0;
117 asn1p_constraint_free(ct_expr);
118 asn1p_constraint_free(ct_parent);
119 return -1;
120 } else {
121 ct_expr->elements[i] = 0;
122 }
123 }
124 asn1p_constraint_free(ct_expr);
125 } else {
126 asn1p_constraint_insert(expr->combined_constraints,
127 ct_expr);
128 }
129 } else {
Lev Walkin38d00172006-09-21 02:21:53 +0000130 _remove_extensions(arg, ct_expr, 1);
Lev Walkinb45e0672004-08-18 05:42:05 +0000131 expr->combined_constraints = ct_expr;
132 }
133
134 return 0;
135}
136
137int
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000138asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
Lev Walkin9288d1c2005-03-10 11:27:13 +0000139 enum asn1p_constraint_type_e real_constraint_type;
Lev Walkind541c252004-09-05 10:36:22 +0000140 unsigned int el;
Lev Walkinb45e0672004-08-18 05:42:05 +0000141 int rvalue = 0;
142 int ret;
Lev Walkinb45e0672004-08-18 05:42:05 +0000143
Lev Walkin9288d1c2005-03-10 11:27:13 +0000144 DEBUG("(\"%s\")", arg->expr->Identifier);
Lev Walkin03850182005-03-10 10:02:50 +0000145
Lev Walkinb45e0672004-08-18 05:42:05 +0000146 if(!ct) return 0;
147
148 /* Don't touch information object classes */
149 switch(ct->type) {
Lev Walkin5253da42004-08-20 13:25:56 +0000150 case ACT_CT_SIZE:
151 case ACT_CT_FROM:
152 if(effective_type && effective_type != ct->type) {
153 FATAL("%s at line %d: "
154 "Incompatible nested %s within %s",
155 arg->expr->Identifier, ct->_lineno,
156 asn1p_constraint_type2str(ct->type),
157 asn1p_constraint_type2str(effective_type)
158 );
159 }
160 effective_type = ct->type;
161 break;
Lev Walkinb45e0672004-08-18 05:42:05 +0000162 case ACT_CT_WCOMP:
163 case ACT_CT_WCOMPS:
164 case ACT_CA_CRC:
165 return 0;
166 default:
167 break;
168 }
169
Lev Walkin9288d1c2005-03-10 11:27:13 +0000170 real_constraint_type = effective_type ? effective_type : ct->type;
171
Lev Walkin5253da42004-08-20 13:25:56 +0000172 if(etype != A1TC_INVALID) {
Lev Walkin5253da42004-08-20 13:25:56 +0000173
Lev Walkin4b553412005-08-14 14:45:44 +0000174 ret = asn1constraint_compatible(etype, real_constraint_type,
175 arg->flags & A1F_EXTENDED_SizeConstraint);
Lev Walkinb45e0672004-08-18 05:42:05 +0000176 switch(ret) {
177 case -1: /* If unknown, assume OK. */
178 case 1:
179 break;
180 case 0:
181 default:
182 FATAL("%s at line %d: "
183 "Constraint type %s is not applicable to %s",
184 arg->expr->Identifier, ct->_lineno,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000185 asn1p_constraint_type2str(real_constraint_type),
Lev Walkin5253da42004-08-20 13:25:56 +0000186 ASN_EXPR_TYPE2STR(etype)
Lev Walkinb45e0672004-08-18 05:42:05 +0000187 );
188 rvalue = -1;
189 break;
190 }
191 } else {
192 WARNING("%s at line %d: "
193 "Constraints ignored: Unresolved parent type",
194 arg->expr->Identifier, arg->expr->_lineno);
195 }
196
Lev Walkin5253da42004-08-20 13:25:56 +0000197 /*
198 * Resolve all possible references, wherever they occur.
199 */
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000200 if(ct->containedSubtype) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000201 ret = constraint_type_resolve(arg, ct);
202 RET2RVAL(ret, rvalue);
203 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000204 if(ct->value && ct->value->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700205 ret = constraint_value_resolve(arg, &ct->value, real_constraint_type);
206 RET2RVAL(ret, rvalue);
Lev Walkinb45e0672004-08-18 05:42:05 +0000207 }
208 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700209 ret = constraint_value_resolve(arg, &ct->range_start,
210 real_constraint_type);
211 RET2RVAL(ret, rvalue);
Lev Walkinb45e0672004-08-18 05:42:05 +0000212 }
213 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700214 ret = constraint_value_resolve(arg, &ct->range_stop,
215 real_constraint_type);
216 RET2RVAL(ret, rvalue);
Lev Walkinb45e0672004-08-18 05:42:05 +0000217 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800218 if (ct->value && ct->value->type == ATV_UNPARSED && etype == A1TC_CLASSDEF) {
219 ret = constraint_object_resolve(arg, ct->value);
220 RET2RVAL(ret, rvalue);
221 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000222
Lev Walkinc0e03b92017-08-22 01:48:23 -0700223 /*
224 * Proceed recursively.
225 */
226 for(el = 0; el < ct->el_count; el++) {
227 ret = asn1constraint_resolve(arg, ct->elements[el], etype,
228 effective_type);
229 RET2RVAL(ret, rvalue);
230 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000231
Lev Walkinc0e03b92017-08-22 01:48:23 -0700232 return rvalue;
Lev Walkinb45e0672004-08-18 05:42:05 +0000233}
234
235static void
Lev Walkin38d00172006-09-21 02:21:53 +0000236_remove_extensions(arg_t *arg, asn1p_constraint_t *ct, int forgive_last) {
Lev Walkind541c252004-09-05 10:36:22 +0000237 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +0000238
Lev Walkin38d00172006-09-21 02:21:53 +0000239 if(!ct) return;
240
Lev Walkinb45e0672004-08-18 05:42:05 +0000241 for(i = 0; i < ct->el_count; i++) {
242 if(ct->elements[i]->type == ACT_EL_EXT)
243 break;
Lev Walkin38d00172006-09-21 02:21:53 +0000244 if(forgive_last && ct->type == ACT_CA_SET
245 && i + 1 == ct->el_count)
246 return;
247 _remove_extensions(arg, ct->elements[i], 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000248 }
249
250 /* Remove the elements at and after the extensibility mark */
251 for(; i < ct->el_count; ct->el_count--) {
252 asn1p_constraint_t *rm;
253 rm = ct->elements[ct->el_count-1];
254 asn1p_constraint_free(rm);
255 }
256
257 if(i < ct->el_size)
258 ct->elements[i] = 0;
259}
260
Lev Walkind523ea42017-09-06 22:15:08 -0700261static asn1p_ref_t *
262get_reference_from(asn1p_constraint_t *ct) {
263 if(ct->containedSubtype->type == ATV_REFERENCED) {
264 return ct->containedSubtype->value.reference;
265 } else if(ct->containedSubtype->type == ATV_TYPE) {
266 if(ct->containedSubtype->value.v_type->expr_type == A1TC_REFERENCE) {
267 return ct->containedSubtype->value.v_type->reference;
268 }
269 }
270 return NULL;
271}
272
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000273static int
274constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
Lev Walkind523ea42017-09-06 22:15:08 -0700275 asn1p_constraint_t *ct_expr;
276 int ret;
Bi-Ruei, Chiu50934ba2017-09-11 08:50:59 +0800277 asn1p_expr_t *rtype = (asn1p_expr_t *)0;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000278
Lev Walkind523ea42017-09-06 22:15:08 -0700279 DEBUG("(\"%s\")", asn1f_printable_value(ct->containedSubtype));
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000280
Lev Walkind523ea42017-09-06 22:15:08 -0700281 if(ct->containedSubtype->type == ATV_VALUESET) {
282 ct_expr = ct->containedSubtype->value.constraint;
283 DEBUG("Found %s in constraints", "ValueSet");
284 } else if(get_reference_from(ct)) {
Lev Walkind523ea42017-09-06 22:15:08 -0700285 arg_t tmparg;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000286
Lev Walkinc0e03b92017-08-22 01:48:23 -0700287 rtype = asn1f_lookup_symbol(arg, arg->expr->rhs_pspecs,
Lev Walkind523ea42017-09-06 22:15:08 -0700288 get_reference_from(ct));
Lev Walkinc0e03b92017-08-22 01:48:23 -0700289 if(!rtype) {
Lev Walkind523ea42017-09-06 22:15:08 -0700290 FATAL(
291 "Cannot find type \"%s\" in constraints "
292 "at line %d",
293 asn1f_printable_value(ct->containedSubtype), ct->_lineno);
294 return -1;
295 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000296
Lev Walkind523ea42017-09-06 22:15:08 -0700297 tmparg = *arg;
298 tmparg.expr = rtype;
299 tmparg.mod = rtype->module;
300 ret = asn1constraint_pullup(&tmparg);
301 if(ret) return ret;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000302
Bi-Ruei, Chiu50934ba2017-09-11 08:50:59 +0800303 if(rtype->ioc_table) {
304 if(!arg->expr->ioc_table)
305 arg->expr->ioc_table = asn1p_ioc_table_new();
306 asn1p_ioc_table_append(arg->expr->ioc_table, rtype->ioc_table);
307 asn1p_value_free(ct->containedSubtype);
308 ct->containedSubtype = NULL;
309 }
310
Lev Walkind523ea42017-09-06 22:15:08 -0700311 ct_expr = rtype->combined_constraints;
312 if(!ct_expr) return 0;
313 } else {
314 FATAL("Unsupported constraint kind %s at line %d",
315 asn1f_printable_value(ct->containedSubtype), ct->_lineno);
316 return -1;
317 }
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000318
Lev Walkind523ea42017-09-06 22:15:08 -0700319 ct_expr = asn1p_constraint_clone(ct_expr);
320 assert(ct_expr);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000321
Lev Walkind523ea42017-09-06 22:15:08 -0700322 _remove_extensions(arg, ct_expr, 0);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000323
Lev Walkind523ea42017-09-06 22:15:08 -0700324 if(ct_expr->type == ACT_CA_SET) {
325 unsigned int i;
326 for(i = 0; i < ct_expr->el_count; i++) {
327 if(asn1p_constraint_insert(
328 ct, ct_expr->elements[i])) {
329 asn1p_constraint_free(ct_expr);
330 return -1;
331 } else {
332 ct_expr->elements[i] = 0;
333 }
334 }
335 asn1p_constraint_free(ct_expr);
336 } else {
337 ret = asn1p_constraint_insert(ct, ct_expr);
338 assert(ret == 0);
339 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000340
Lev Walkind523ea42017-09-06 22:15:08 -0700341 ct->type = ACT_CA_SET;
Bi-Ruei, Chiu50934ba2017-09-11 08:50:59 +0800342
343 /* keep constrainedSubtype field for future usage,
344 if valueset has not been resolved yet. */
345 if(rtype &&
346 (rtype->meta_type == AMT_VALUESET) &&
347 (!rtype->ioc_table))
348 return 0;
349
Lev Walkind523ea42017-09-06 22:15:08 -0700350 asn1p_value_free(ct->containedSubtype);
351 ct->containedSubtype = NULL;
352
353 return 0;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000354}
Lev Walkinb45e0672004-08-18 05:42:05 +0000355
356static int
Lev Walkinc0e03b92017-08-22 01:48:23 -0700357constraint_value_resolve(arg_t *arg, asn1p_value_t **value,
358 enum asn1p_constraint_type_e real_ctype) {
359 asn1p_expr_t static_expr;
360 arg_t tmparg;
Lev Walkinb45e0672004-08-18 05:42:05 +0000361 int rvalue = 0;
362 int ret;
363
Lev Walkin9288d1c2005-03-10 11:27:13 +0000364 DEBUG("(\"%s\", within <%s>)",
365 asn1f_printable_value(*value),
366 asn1p_constraint_type2str(real_ctype));
367
368 static_expr = *arg->expr;
Lev Walkinb45e0672004-08-18 05:42:05 +0000369 static_expr.value = *value;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000370 static_expr.meta_type = AMT_VALUE;
Lev Walkinc0e03b92017-08-22 01:48:23 -0700371 tmparg = *arg;
372 tmparg.mod = arg->expr->module;
373 tmparg.expr = &static_expr;
374 ret = asn1f_value_resolve(&tmparg, &static_expr, &real_ctype);
Lev Walkinb45e0672004-08-18 05:42:05 +0000375 RET2RVAL(ret, rvalue);
376 assert(static_expr.value);
377 *value = static_expr.value;
378
379 return rvalue;
380}
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000381
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800382static int
383constraint_object_resolve(arg_t *arg, asn1p_value_t *value) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700384 asn1p_expr_t tmp_expr = *arg->expr;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800385 asn1p_expr_t *saved_expr = arg->expr;
386
Lev Walkinea6635b2017-08-06 23:23:04 -0700387 tmp_expr.meta_type = AMT_VALUESET;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800388 tmp_expr.expr_type = A1TC_REFERENCE;
389 tmp_expr.value = value;
390 arg->expr = &tmp_expr;
391
392 if (asn1f_check_class_object(arg)) {
393 arg->expr = saved_expr;
394 FATAL("Parsing ObjectSet %s failed at %d", arg->expr->Identifier,
395 arg->expr->_lineno);
396 return -1;
397 }
398
399 arg->expr = saved_expr;
400 return 0;
401}
402