blob: 46eddaaa954377b7aa960588e3789654c519d5e9 [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:
24 break;
25 default:
26 return 0; /* Nothing to do */
27 }
28
29 if(expr->expr_type == A1TC_REFERENCE) {
30 asn1p_ref_t *ref = expr->reference;
Lev Walkinb45e0672004-08-18 05:42:05 +000031 asn1p_expr_t *parent_expr;
32
33 assert(ref);
Lev Walkinc0e03b92017-08-22 01:48:23 -070034 parent_expr = asn1f_lookup_symbol(arg, expr->rhs_pspecs, ref);
35 if(!parent_expr) {
Lev Walkinb45e0672004-08-18 05:42:05 +000036 if(errno != EEXIST) {
37 DEBUG("\tWhile fetching parent constraints: "
38 "type \"%s\" not found: %s",
39 asn1f_printable_reference(ref),
40 strerror(errno));
41 return -1;
42 } else {
43 /*
44 * -fknown-extern-type is given.
45 * Assume there are no constraints there.
46 */
47 WARNING("External type \"%s\": "
48 "assuming no constraints",
49 asn1f_printable_reference(ref));
50 ct_parent = 0;
51 }
52 } else {
53 arg->expr = parent_expr;
54 ret = asn1constraint_pullup(arg);
55 arg->expr = expr;
56 if(ret) return ret;
57
58 ct_parent = parent_expr->combined_constraints;
59 }
Lev Walkinc0e03b92017-08-22 01:48:23 -070060 } else {
Lev Walkinb45e0672004-08-18 05:42:05 +000061 ct_parent = 0;
62 }
63
64 ct_expr = expr->constraints;
65
66 if(!ct_parent && !ct_expr)
67 return 0; /* No constraints to consider */
68
Lev Walkin7ec9b4c2005-03-20 12:57:21 +000069 /*
70 * Resolve constraints, if not already resolved.
71 */
72 top_parent = asn1f_find_terminal_type(arg, arg->expr);
Lev Walkinc0e03b92017-08-22 01:48:23 -070073 ret = asn1constraint_resolve(
74 arg, ct_expr, top_parent ? top_parent->expr_type : A1TC_INVALID, 0);
75 if(ret) return ret;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +000076
77 /*
78 * Copy parent type constraints.
79 */
Lev Walkinb45e0672004-08-18 05:42:05 +000080 if(ct_parent) {
81 ct_parent = asn1p_constraint_clone(ct_parent);
82 assert(ct_parent);
83 }
84
85 /*
86 * If the current type does not have constraints, it inherits
87 * the constraints of a parent.
88 */
89 if(ct_parent && !ct_expr) {
90 expr->combined_constraints = ct_parent;
91 return 0;
92 }
93
94 ct_expr = asn1p_constraint_clone(ct_expr);
95 assert(ct_expr);
96
97 /*
98 * Now we have a set of current expression's constraints,
99 * and an optional set of the parent expression's constraints.
100 */
101
102 if(ct_parent) {
103 /*
104 * If we have a parent, remove all the extensions (46.4).
105 */
Lev Walkin38d00172006-09-21 02:21:53 +0000106 _remove_extensions(arg, ct_parent, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000107
108 expr->combined_constraints = ct_parent;
109 if(ct_expr->type == ACT_CA_SET) {
Lev Walkind541c252004-09-05 10:36:22 +0000110 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +0000111 for(i = 0; i < ct_expr->el_count; i++) {
112 if(asn1p_constraint_insert(
113 expr->combined_constraints,
114 ct_expr->elements[i])) {
115 expr->combined_constraints = 0;
116 asn1p_constraint_free(ct_expr);
117 asn1p_constraint_free(ct_parent);
118 return -1;
119 } else {
120 ct_expr->elements[i] = 0;
121 }
122 }
123 asn1p_constraint_free(ct_expr);
124 } else {
125 asn1p_constraint_insert(expr->combined_constraints,
126 ct_expr);
127 }
128 } else {
Lev Walkin38d00172006-09-21 02:21:53 +0000129 _remove_extensions(arg, ct_expr, 1);
Lev Walkinb45e0672004-08-18 05:42:05 +0000130 expr->combined_constraints = ct_expr;
131 }
132
133 return 0;
134}
135
136int
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000137asn1constraint_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 +0000138 enum asn1p_constraint_type_e real_constraint_type;
Lev Walkind541c252004-09-05 10:36:22 +0000139 unsigned int el;
Lev Walkinb45e0672004-08-18 05:42:05 +0000140 int rvalue = 0;
141 int ret;
Lev Walkinb45e0672004-08-18 05:42:05 +0000142
Lev Walkin9288d1c2005-03-10 11:27:13 +0000143 DEBUG("(\"%s\")", arg->expr->Identifier);
Lev Walkin03850182005-03-10 10:02:50 +0000144
Lev Walkinb45e0672004-08-18 05:42:05 +0000145 if(!ct) return 0;
146
147 /* Don't touch information object classes */
148 switch(ct->type) {
Lev Walkin5253da42004-08-20 13:25:56 +0000149 case ACT_CT_SIZE:
150 case ACT_CT_FROM:
151 if(effective_type && effective_type != ct->type) {
152 FATAL("%s at line %d: "
153 "Incompatible nested %s within %s",
154 arg->expr->Identifier, ct->_lineno,
155 asn1p_constraint_type2str(ct->type),
156 asn1p_constraint_type2str(effective_type)
157 );
158 }
159 effective_type = ct->type;
160 break;
Lev Walkinb45e0672004-08-18 05:42:05 +0000161 case ACT_CT_WCOMP:
162 case ACT_CT_WCOMPS:
163 case ACT_CA_CRC:
164 return 0;
165 default:
166 break;
167 }
168
Lev Walkin9288d1c2005-03-10 11:27:13 +0000169 real_constraint_type = effective_type ? effective_type : ct->type;
170
Lev Walkin5253da42004-08-20 13:25:56 +0000171 if(etype != A1TC_INVALID) {
Lev Walkin5253da42004-08-20 13:25:56 +0000172
Lev Walkin4b553412005-08-14 14:45:44 +0000173 ret = asn1constraint_compatible(etype, real_constraint_type,
174 arg->flags & A1F_EXTENDED_SizeConstraint);
Lev Walkinb45e0672004-08-18 05:42:05 +0000175 switch(ret) {
176 case -1: /* If unknown, assume OK. */
177 case 1:
178 break;
179 case 0:
180 default:
181 FATAL("%s at line %d: "
182 "Constraint type %s is not applicable to %s",
183 arg->expr->Identifier, ct->_lineno,
Lev Walkin9288d1c2005-03-10 11:27:13 +0000184 asn1p_constraint_type2str(real_constraint_type),
Lev Walkin5253da42004-08-20 13:25:56 +0000185 ASN_EXPR_TYPE2STR(etype)
Lev Walkinb45e0672004-08-18 05:42:05 +0000186 );
187 rvalue = -1;
188 break;
189 }
190 } else {
191 WARNING("%s at line %d: "
192 "Constraints ignored: Unresolved parent type",
193 arg->expr->Identifier, arg->expr->_lineno);
194 }
195
Lev Walkin5253da42004-08-20 13:25:56 +0000196 /*
197 * Resolve all possible references, wherever they occur.
198 */
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000199 if(ct->containedSubtype) {
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000200 ret = constraint_type_resolve(arg, ct);
201 RET2RVAL(ret, rvalue);
202 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000203 if(ct->value && ct->value->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700204 ret = constraint_value_resolve(arg, &ct->value, real_constraint_type);
205 RET2RVAL(ret, rvalue);
Lev Walkinb45e0672004-08-18 05:42:05 +0000206 }
207 if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700208 ret = constraint_value_resolve(arg, &ct->range_start,
209 real_constraint_type);
210 RET2RVAL(ret, rvalue);
Lev Walkinb45e0672004-08-18 05:42:05 +0000211 }
212 if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700213 ret = constraint_value_resolve(arg, &ct->range_stop,
214 real_constraint_type);
215 RET2RVAL(ret, rvalue);
Lev Walkinb45e0672004-08-18 05:42:05 +0000216 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800217 if (ct->value && ct->value->type == ATV_UNPARSED && etype == A1TC_CLASSDEF) {
218 ret = constraint_object_resolve(arg, ct->value);
219 RET2RVAL(ret, rvalue);
220 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000221
Lev Walkinc0e03b92017-08-22 01:48:23 -0700222 /*
223 * Proceed recursively.
224 */
225 for(el = 0; el < ct->el_count; el++) {
226 ret = asn1constraint_resolve(arg, ct->elements[el], etype,
227 effective_type);
228 RET2RVAL(ret, rvalue);
229 }
Lev Walkinb45e0672004-08-18 05:42:05 +0000230
Lev Walkinc0e03b92017-08-22 01:48:23 -0700231 return rvalue;
Lev Walkinb45e0672004-08-18 05:42:05 +0000232}
233
234static void
Lev Walkin38d00172006-09-21 02:21:53 +0000235_remove_extensions(arg_t *arg, asn1p_constraint_t *ct, int forgive_last) {
Lev Walkind541c252004-09-05 10:36:22 +0000236 unsigned int i;
Lev Walkinb45e0672004-08-18 05:42:05 +0000237
Lev Walkin38d00172006-09-21 02:21:53 +0000238 if(!ct) return;
239
Lev Walkinb45e0672004-08-18 05:42:05 +0000240 for(i = 0; i < ct->el_count; i++) {
241 if(ct->elements[i]->type == ACT_EL_EXT)
242 break;
Lev Walkin38d00172006-09-21 02:21:53 +0000243 if(forgive_last && ct->type == ACT_CA_SET
244 && i + 1 == ct->el_count)
245 return;
246 _remove_extensions(arg, ct->elements[i], 0);
Lev Walkinb45e0672004-08-18 05:42:05 +0000247 }
248
249 /* Remove the elements at and after the extensibility mark */
250 for(; i < ct->el_count; ct->el_count--) {
251 asn1p_constraint_t *rm;
252 rm = ct->elements[ct->el_count-1];
253 asn1p_constraint_free(rm);
254 }
255
256 if(i < ct->el_size)
257 ct->elements[i] = 0;
258}
259
Lev Walkind523ea42017-09-06 22:15:08 -0700260static asn1p_ref_t *
261get_reference_from(asn1p_constraint_t *ct) {
262 if(ct->containedSubtype->type == ATV_REFERENCED) {
263 return ct->containedSubtype->value.reference;
264 } else if(ct->containedSubtype->type == ATV_TYPE) {
265 if(ct->containedSubtype->value.v_type->expr_type == A1TC_REFERENCE) {
266 return ct->containedSubtype->value.v_type->reference;
267 }
268 }
269 return NULL;
270}
271
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000272static int
273constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
Lev Walkind523ea42017-09-06 22:15:08 -0700274 asn1p_constraint_t *ct_expr;
275 int ret;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000276
Lev Walkind523ea42017-09-06 22:15:08 -0700277 DEBUG("(\"%s\")", asn1f_printable_value(ct->containedSubtype));
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000278
Lev Walkind523ea42017-09-06 22:15:08 -0700279 if(ct->containedSubtype->type == ATV_VALUESET) {
280 ct_expr = ct->containedSubtype->value.constraint;
281 DEBUG("Found %s in constraints", "ValueSet");
282 } else if(get_reference_from(ct)) {
283 asn1p_expr_t *rtype;
284 arg_t tmparg;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000285
Lev Walkinc0e03b92017-08-22 01:48:23 -0700286 rtype = asn1f_lookup_symbol(arg, arg->expr->rhs_pspecs,
Lev Walkind523ea42017-09-06 22:15:08 -0700287 get_reference_from(ct));
Lev Walkinc0e03b92017-08-22 01:48:23 -0700288 if(!rtype) {
Lev Walkind523ea42017-09-06 22:15:08 -0700289 FATAL(
290 "Cannot find type \"%s\" in constraints "
291 "at line %d",
292 asn1f_printable_value(ct->containedSubtype), ct->_lineno);
293 return -1;
294 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000295
Lev Walkind523ea42017-09-06 22:15:08 -0700296 tmparg = *arg;
297 tmparg.expr = rtype;
298 tmparg.mod = rtype->module;
299 ret = asn1constraint_pullup(&tmparg);
300 if(ret) return ret;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000301
Lev Walkind523ea42017-09-06 22:15:08 -0700302 ct_expr = rtype->combined_constraints;
303 if(!ct_expr) return 0;
304 } else {
305 FATAL("Unsupported constraint kind %s at line %d",
306 asn1f_printable_value(ct->containedSubtype), ct->_lineno);
307 return -1;
308 }
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000309
Lev Walkind523ea42017-09-06 22:15:08 -0700310 ct_expr = asn1p_constraint_clone(ct_expr);
311 assert(ct_expr);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000312
Lev Walkind523ea42017-09-06 22:15:08 -0700313 _remove_extensions(arg, ct_expr, 0);
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000314
Lev Walkind523ea42017-09-06 22:15:08 -0700315 if(ct_expr->type == ACT_CA_SET) {
316 unsigned int i;
317 for(i = 0; i < ct_expr->el_count; i++) {
318 if(asn1p_constraint_insert(
319 ct, ct_expr->elements[i])) {
320 asn1p_constraint_free(ct_expr);
321 return -1;
322 } else {
323 ct_expr->elements[i] = 0;
324 }
325 }
326 asn1p_constraint_free(ct_expr);
327 } else {
328 ret = asn1p_constraint_insert(ct, ct_expr);
329 assert(ret == 0);
330 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000331
Lev Walkind523ea42017-09-06 22:15:08 -0700332 ct->type = ACT_CA_SET;
333 asn1p_value_free(ct->containedSubtype);
334 ct->containedSubtype = NULL;
335
336 return 0;
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000337}
Lev Walkinb45e0672004-08-18 05:42:05 +0000338
339static int
Lev Walkinc0e03b92017-08-22 01:48:23 -0700340constraint_value_resolve(arg_t *arg, asn1p_value_t **value,
341 enum asn1p_constraint_type_e real_ctype) {
342 asn1p_expr_t static_expr;
343 arg_t tmparg;
Lev Walkinb45e0672004-08-18 05:42:05 +0000344 int rvalue = 0;
345 int ret;
346
Lev Walkin9288d1c2005-03-10 11:27:13 +0000347 DEBUG("(\"%s\", within <%s>)",
348 asn1f_printable_value(*value),
349 asn1p_constraint_type2str(real_ctype));
350
351 static_expr = *arg->expr;
Lev Walkinb45e0672004-08-18 05:42:05 +0000352 static_expr.value = *value;
Lev Walkin9288d1c2005-03-10 11:27:13 +0000353 static_expr.meta_type = AMT_VALUE;
Lev Walkinc0e03b92017-08-22 01:48:23 -0700354 tmparg = *arg;
355 tmparg.mod = arg->expr->module;
356 tmparg.expr = &static_expr;
357 ret = asn1f_value_resolve(&tmparg, &static_expr, &real_ctype);
Lev Walkinb45e0672004-08-18 05:42:05 +0000358 RET2RVAL(ret, rvalue);
359 assert(static_expr.value);
360 *value = static_expr.value;
361
362 return rvalue;
363}
Lev Walkin7ec9b4c2005-03-20 12:57:21 +0000364
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800365static int
366constraint_object_resolve(arg_t *arg, asn1p_value_t *value) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700367 asn1p_expr_t tmp_expr = *arg->expr;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800368 asn1p_expr_t *saved_expr = arg->expr;
369
Lev Walkinea6635b2017-08-06 23:23:04 -0700370 tmp_expr.meta_type = AMT_VALUESET;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800371 tmp_expr.expr_type = A1TC_REFERENCE;
372 tmp_expr.value = value;
373 arg->expr = &tmp_expr;
374
375 if (asn1f_check_class_object(arg)) {
376 arg->expr = saved_expr;
377 FATAL("Parsing ObjectSet %s failed at %d", arg->expr->Identifier,
378 arg->expr->_lineno);
379 return -1;
380 }
381
382 arg->expr = saved_expr;
383 return 0;
384}
385