blob: dd54224daec37ed67bbc287d4f6753db3bb8bcb4 [file] [log] [blame]
vlm1d036692004-08-19 13:29:46 +00001#include "asn1c_internal.h"
2#include "asn1c_constraint.h"
3
4#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
5#include <asn1fix_export.h> /* other exportable stuff from libasn1fix */
6
7static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);
8static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype);
9static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);
10static asn1p_expr_type_e _find_terminal_type(arg_t *arg);
11static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1_integer_t natural_start, asn1_integer_t natural_stop);
12
13#define MKID(id) asn1c_make_identifier(0, (id), 0)
14
15static int global_compile_mark;
16
17int
18asn1c_emit_constraint_checking_code(arg_t *arg) {
19 asn1cnst_range_t *r_size;
20 asn1cnst_range_t *r_value;
21 asn1p_expr_t *expr = arg->expr;
22 asn1p_expr_type_e etype;
23 asn1p_constraint_t *ct;
24 int got_something = 0;
25
26 ct = expr->combined_constraints;
27 if(ct == NULL)
28 return 1; /* No additional constraints defined */
29
30 etype = _find_terminal_type(arg);
31
32 r_value=asn1constraint_compute_PER_range(etype, ct, ACT_EL_RANGE, 0, 0);
33 r_size = asn1constraint_compute_PER_range(etype, ct, ACT_CT_SIZE, 0, 0);
34 if(r_value) {
35 if(r_value->not_PER_visible
36 || r_value->extensible
37 || r_value->empty_constraint
38 || (r_value->left.type == ARE_MIN
39 && r_value->right.type == ARE_MAX)
40 || (etype == ASN_BASIC_BOOLEAN
41 && r_value->left.value == 0
42 && r_value->right.value == 1)
43 ) {
44 asn1constraint_range_free(r_value);
45 r_value = 0;
46 }
47 }
48 if(r_size) {
49 if(r_size->not_PER_visible
50 || r_size->extensible
51 || r_size->empty_constraint
52 || (r_size->left.value == 0 /* or .type == MIN */
53 && r_size->right.type == ARE_MAX)
54 ) {
55 asn1constraint_range_free(r_size);
56 r_size = 0;
57 }
58 }
59
60 OUT("const %s_t *st = sptr;\n", MKID(arg->expr->Identifier));
61
62 if(r_size || r_value) {
63 if(r_size) {
64 OUT("size_t size;\n");
65 }
66 if(r_value)
67 switch(etype) {
68 case ASN_BASIC_INTEGER:
69 case ASN_BASIC_ENUMERATED:
70 OUT("long value;\n");
71 break;
72 case ASN_BASIC_BOOLEAN:
73 OUT("int value;\n");
74 break;
75 default:
76 break;
77 }
78 }
79
80 OUT("\n");
81
82 /*
83 * Protection against null input.
84 */
85 OUT("if(!sptr) {\n");
86 INDENT(+1);
87 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
88 OUT("\t\"%%s: value not given\", td->name);\n");
89 OUT("return -1;\n");
90 INDENT(-1);
91 OUT("}\n");
92 OUT("\n");
93
94 if(r_value)
95 emit_value_determination_code(arg, etype);
96 if(r_size)
97 emit_size_determination_code(arg, etype);
98
99 /*
100 * Here is an if() {} else {} constaint checking code.
101 */
102 OUT("\n");
103 OUT("if(");
104 INDENT(+1);
105 if(r_size) {
106 if(got_something++) { OUT("\n"); OUT(" && "); }
107 OUT("(");
108 emit_range_comparison_code(arg, r_size, "size", 0, -1);
109 OUT(")");
110 }
111 if(r_value) {
112 if(got_something++) { OUT("\n"); OUT(" && "); }
113 OUT("(");
114 if(etype == ASN_BASIC_BOOLEAN)
115 emit_range_comparison_code(arg, r_value,
116 "value", 0, 1);
117 else
118 emit_range_comparison_code(arg, r_value,
119 "value", -1, -1);
120 OUT(")");
121 }
122 if(ct->_compile_mark) {
123 if(got_something++) { OUT("\n"); OUT(" && "); }
124 OUT("check_permitted_alphabet_%d(sptr)",
125 ct->_compile_mark);
126 }
127 if(!got_something) {
128 OUT("1 /* No applicable constraints whatsoever */");
129 }
130 INDENT(-1);
131 OUT(") {\n");
132 INDENT(+1);
133 OUT("/* Constraint check succeeded */\n");
134 OUT("return 1;\n");
135 INDENT(-1);
136 OUT("} else {\n");
137 INDENT(+1);
138 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
139 OUT("\t\"%%s: constraint failed\", td->name);\n");
140 OUT("return -1;\n");
141 INDENT(-1);
142 OUT("}\n");
143
144 return 0;
145}
146
147int
148asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct) {
149 asn1_integer_t range_start;
150 asn1_integer_t range_stop;
151 asn1p_expr_type_e etype;
152 asn1cnst_range_t *range;
153 int table[256];
154 int use_table;
155
156 if(!ct) ct = arg->expr->combined_constraints;
157 if(!ct) return 0;
158
159 etype = _find_terminal_type(arg);
160
161 range = asn1constraint_compute_PER_range(etype, ct, ACT_CT_FROM, 0, 0);
162 if(!range) return 0;
163
164 if(range->not_PER_visible
165 || range->extensible
166 || range->empty_constraint) {
167 asn1constraint_range_free(range);
168 return 0;
169 }
170
171 range_start = range->left.value;
172 range_stop = range->right.value;
173 assert(range->left.type == ARE_VALUE);
174 assert(range->right.type == ARE_VALUE);
175 assert(range_start <= range_stop);
176
177 range_start = 0; /* Force old behavior */
178
179 /*
180 * Check if we need a test table to check the alphabet.
181 */
182 use_table = 1;
183 if((range_stop - range_start) > 255)
184 use_table = 0;
185 if(range->el_count == 0)
186 use_table = 0;
187
188 if(!ct->_compile_mark)
189 ct->_compile_mark = ++global_compile_mark;
190
191 if(use_table) {
192 int i, n = 0;
193 int untl;
194 memset(table, 0, sizeof(table));
195 for(i = -1; i < range->el_count; i++) {
196 asn1cnst_range_t *r;
197 asn1_integer_t v;
198 if(i == -1) {
199 if(range->el_count) continue;
200 r = range;
201 } else {
202 r = range->elements[i];
203 }
204 for(v = r->left.value; v <= r->right.value; v++) {
205 assert((v - range_start) >= 0);
206 assert((v - range_start) < 256);
207 table[v - range_start] = ++n;
208 }
209 }
210
211 OUT("static int permitted_alphabet_table_%d[256] = {\n",
212 ct->_compile_mark);
213 untl = (range_stop - range_start) + 1;
214 untl += (untl % 16)?16 - (untl % 16):0;
215 for(n = 0; n < untl; n++) {
216 OUT("%d,", table[n]?1:0);
217 if(!((n+1) % 16)) {
218 int c;
219 if(!n) {
220 OUT("\n");
221 continue;
222 }
223 OUT("\t/* ");
224 for(c = n - 15; c <= n; c++) {
225 if(table[c]) {
226 int a = c + range_start;
227 if(a > 0x20 && a < 0x80)
228 OUT("%c", a);
229 else
230 OUT(".");
231 } else {
232 OUT(" ");
233 }
234 }
235 OUT(" */");
236 OUT("\n");
237 }
238 }
239 OUT("};\n");
240 OUT("\n");
241 }
242
243 OUT("static int check_permitted_alphabet_%d(const void *sptr) {\n",
244 ct->_compile_mark);
245 INDENT(+1);
246 if(use_table) {
247 OUT("int *table = permitted_alphabet_table_%d;\n",
248 ct->_compile_mark);
249 emit_alphabet_check_loop(arg, 0);
250 } else {
251 emit_alphabet_check_loop(arg, range);
252 }
253 OUT("return 1;\n");
254 INDENT(-1);
255 OUT("}\n");
256 OUT("\n");
257
258 asn1constraint_range_free(range);
259
260 return 0;
261}
262
263static int
264emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range) {
265 asn1p_expr_type_e etype;
266 asn1_integer_t natural_stop;
267
268 etype = _find_terminal_type(arg);
269
270 OUT("/* The underlying type is %s */\n",
271 ASN_EXPR_TYPE2STR(etype));
272 OUT("const %s_t *st = sptr;\n", MKID(arg->expr->Identifier));
273
274 switch(etype) {
275 case ASN_STRING_UTF8String:
276 OUT("uint8_t *ch = st->buf;\n");
277 OUT("uint8_t *end = ch + st->size;\n");
278 OUT("\n");
279 OUT("for(; ch < end; ch++) {\n");
280 INDENT(+1);
281 OUT("uint8_t cv = *ch;\n");
282 if(!range) OUT("if(cv >= 0x80) return 0;\n");
283 natural_stop = 0xffffffffUL;
284 break;
285 case ASN_STRING_UniversalString:
286 OUT("uint32_t *ch = st->buf;\n");
287 OUT("uint32_t *end = ch + st->size;\n");
288 OUT("\n");
289 OUT("if(st->size % 4) return 0; /* (size%4)! */\n");
290 OUT("for(; ch < end; ch++) {\n");
291 INDENT(+1);
292 OUT("uint32_t cv = (((uint8_t *)ch)[0] << 24)\n");
293 OUT("\t\t| (((uint8_t *)ch)[1] << 16)\n");
294 OUT("\t\t| (((uint8_t *)ch)[2] << 8)\n");
295 OUT("\t\t| ((uint8_t *)ch)[3]\n");
296 if(!range) OUT("if(cv > 255) return 0;\n");
297 natural_stop = 0xffffffffUL;
298 break;
299 case ASN_STRING_BMPString:
300 OUT("uint16_t *ch = st->buf;\n");
301 OUT("uint16_t *end = ch + st->size;\n");
302 OUT("\n");
303 OUT("if(st->size % 2) return 0; /* (size%2)! */\n");
304 OUT("for(; ch < end; ch++) {\n");
305 INDENT(+1);
306 OUT("uint16_t cv = (((uint8_t *)ch)[0] << 8)\n");
307 OUT("\t\t| ((uint8_t *)ch)[1];\n");
308 if(!range) OUT("if(cv > 255) return 0;\n");
309 natural_stop = 0xffff;
310 break;
311 case ASN_BASIC_OCTET_STRING:
312 default:
313 OUT("uint8_t *ch = st->buf;\n");
314 OUT("uint8_t *end = ch + st->size;\n");
315 OUT("\n");
316 OUT("for(; ch < end; ch++) {\n");
317 INDENT(+1);
318 OUT("uint8_t cv = *ch;\n");
319 natural_stop = 0xff;
320 break;
321 }
322
323 if(range) {
324 OUT("if(!(");
325 emit_range_comparison_code(arg, range, "cv", 0, natural_stop);
326 OUT(")) return 0;\n");
327 } else {
328 OUT("if(!table[cv]) return 0;\n");
329 }
330
331 INDENT(-1);
332 OUT("}\n");
333
334 return 0;
335}
336
337static int
338emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1_integer_t natural_start, asn1_integer_t natural_stop) {
339 int ignore_left;
340 int ignore_right;
341 int i;
342
343 for(i = -1; i < range->el_count; i++) {
344 asn1cnst_range_t *r;
345 if(i == -1) {
346 if(range->el_count) continue;
347 r = range;
348 } else {
349 if(i) OUT(" || ");
350 r = range->elements[i];
351 }
352
353 if(r != range) OUT("(");
354
355 ignore_left = (r->left.type == ARE_MIN)
356 || (natural_start != -1
357 && r->left.value <= natural_start);
358 ignore_right = (r->right.type == ARE_MAX)
359 || (natural_stop != -1
360 && r->right.value >= natural_stop);
361 if(ignore_left && ignore_right) {
362 OUT("1 /* Constraint matches natural range of %s */",
363 varname);
364 continue;
365 }
366
367 if(ignore_left) {
368 OUT("%s <= %lld", varname,
369 (long long)r->right.value);
370 } else if(ignore_right) {
371 OUT("%s >= %lld", varname,
372 (long long)r->left.value);
373 } else if(r->left.value == r->right.value) {
374 OUT("%s == %lld", varname,
375 (long long)r->right.value);
376 } else {
377 OUT("%s >= %lld && %s <= %lld",
378 varname,
379 (long long)r->left.value,
380 varname,
381 (long long)r->right.value);
382 }
383 if(r != range) OUT(")");
384 }
385
386 return 0;
387}
388
389static int
390emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
391
392 switch(etype) {
393 case ASN_BASIC_BIT_STRING:
394 OUT("if(st->size > 0) {\n");
395 OUT("\t/* Size in bits */\n");
396 OUT("\tsize = (st->size - 1) - (st->buf[0] & 0x7);\n");
397 OUT("} else {\n");
398 OUT("\tsize = 0;\n");
399 OUT("}\n");
400 break;
401 case ASN_STRING_UniversalString:
402 OUT("size = st->size >> 2;\t/* 4 byte per character */\n");
403 break;
404 case ASN_STRING_BMPString:
405 OUT("size = st->size >> 1;\t/* 2 byte per character */\n");
406 break;
407 case ASN_STRING_UTF8String:
408 OUT("size = UTF8String_length(st, td->name, app_errlog, app_key);\n");
409 OUT("if(size == (size_t)-1) return -1;\n");
410 break;
411 case ASN_CONSTR_SET_OF:
412 case ASN_CONSTR_SEQUENCE_OF:
413 OUT("{ /* Determine the number of elements */\n");
414 INDENT(+1);
415 OUT("A_%s_OF(void) *list;\n",
416 etype==ASN_CONSTR_SET_OF?"SET":"SEQUENCE");
417 OUT("(void *)list = st;\n");
418 OUT("size = list->count;\n");
419 INDENT(-1);
420 OUT("}\n");
421 break;
422 default:
423 if((etype & ASN_STRING_MASK)
424 || etype == ASN_BASIC_OCTET_STRING) {
425 OUT("size = st->size;\n");
426 break;
427 } else {
428 const char *type_name = ASN_EXPR_TYPE2STR(etype);
429 if(!type_name) type_name = arg->expr->Identifier;
430 WARNING("SizeConstraint is not defined for %s",
431 type_name);
432 OUT_NOINDENT("#warning SizeConstraint "
433 "is not defined for %s!\n", type_name);
434 OUT("size = st->size;\n");
435 }
436 return -1;
437 }
438
439 return 0;
440}
441
442static int
443emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
444
445 switch(etype) {
446 case ASN_BASIC_INTEGER:
447 case ASN_BASIC_ENUMERATED:
448 if(arg->flags & A1C_USE_NATIVE_INTEGERS) {
449 OUT("value = *(int *)st;\n");
450 } else {
451 OUT("if(asn1_INTEGER2long(st, &value)) {\n");
452 INDENT(+1);
453 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
454 OUT("\t\"%%s: value too large\", td->name);\n");
455 OUT("return -1;\n");
456 INDENT(-1);
457 OUT("}\n");
458 }
459 break;
460 case ASN_BASIC_BOOLEAN:
461 OUT("value = (*(int *)st) ? 1 : 0;\n");
462 break;
463 default:
464 WARNING("Value cannot be determined "
465 "for constraint check for %s at line %d\n",
466 arg->expr->Identifier, arg->expr->_lineno);
467 OUT("#error Value cannot be determined for %s at %d\n",
468 arg->expr->Identifier, arg->expr->_lineno);
469 break;
470 }
471
472 return 0;
473}
474
475static asn1p_expr_type_e
476_find_terminal_type(arg_t *arg) {
477 asn1p_expr_t *expr;
478 expr = asn1f_find_terminal_type_ex(arg->asn, arg->mod, arg->expr, NULL);
479 if(expr) return expr->expr_type;
480 return A1TC_INVALID;
481}
482