blob: 3e196f6979de71c9b19a52c6277f69b5feb31453 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
Lev Walkinef4a32b2006-08-28 02:12:49 +00003static int asn1f_fix_bit_string_type(arg_t *arg);
4static int asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype);
Lev Walkinf15320b2004-06-03 03:38:44 +00005static void asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value);
6static int asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype);
7
8int
9asn1f_fix_bit_string(arg_t *arg) {
10 asn1p_expr_t *expr = arg->expr;
11 int r_value = 0;
12 int ret;
13
14 if(expr->meta_type == AMT_VALUE) {
15 asn1p_expr_t *ttype;
16
Lev Walkin03850182005-03-10 10:02:50 +000017 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +000018
Lev Walkin6fec44d2004-08-22 03:10:23 +000019 ttype = asn1f_find_terminal_type(arg, expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000020 if(ttype && ttype->expr_type == ASN_BASIC_BIT_STRING) {
21 ret = asn1f_fix_bit_string_value(arg, ttype);
22 RET2RVAL(ret, r_value);
23 }
24 }
25
Lev Walkinef4a32b2006-08-28 02:12:49 +000026 if(expr->meta_type == AMT_TYPE
27 && expr->expr_type == ASN_BASIC_BIT_STRING) {
28 ret = asn1f_fix_bit_string_type(arg);
29 RET2RVAL(ret, r_value);
30 }
31
Lev Walkinf15320b2004-06-03 03:38:44 +000032 return r_value;
33}
34
Lev Walkinfbfc7bc2006-08-28 02:45:44 +000035static int _compare_value(asn1p_expr_t *expr1, asn1p_expr_t *expr2) {
36 return expr2->value->value.v_integer - expr1->value->value.v_integer;
37}
38
Lev Walkinef4a32b2006-08-28 02:12:49 +000039static int
40asn1f_fix_bit_string_type(arg_t *arg) {
41 asn1p_expr_t *expr = arg->expr;
42 asn1p_expr_t *v;
Lev Walkina0c92902006-08-28 02:24:24 +000043 int r_value = 0;
44 int ret;
Lev Walkinef4a32b2006-08-28 02:12:49 +000045
46 TQ_FOR(v, &(expr->members), next) {
Lev Walkina0c92902006-08-28 02:24:24 +000047 if(v->expr_type == A1TC_EXTENSIBLE) {
48 FATAL("Extension marker (...) is not allowed "
49 "as a BIT STRING NamedBit at line %d ",
50 v->_lineno);
51 return -1;
52 }
Lev Walkinef4a32b2006-08-28 02:12:49 +000053 if(v->expr_type != A1TC_UNIVERVAL) {
54 FATAL("BIT STRING value at line %d "
Lev Walkina0c92902006-08-28 02:24:24 +000055 "is not an identifier", v->_lineno);
Lev Walkinef4a32b2006-08-28 02:12:49 +000056 return -1;
57 }
Lev Walkinceac1542006-08-28 02:30:41 +000058
59 /* 21.1 */
60 if(v->value == NULL) {
61 FATAL("BIT STRING NamedBit value at line %d "
62 "must be explicitly specified in braces",
63 v->_lineno);
64 return -1;
65 } else if(v->value->type == ATV_REFERENCED) {
66 /* Resolve the value */
Lev Walkinc0e03b92017-08-22 01:48:23 -070067 if(asn1f_value_resolve(arg, v, 0))
68 return -1;
Lev Walkinceac1542006-08-28 02:30:41 +000069 }
70 if(v->value->type != ATV_INTEGER
71 || v->value->value.v_integer < 0) {
72 FATAL("BIT STRING NamedBit value at line %d: "
73 "non-negative integer value expected",
74 v->_lineno);
75 return -1;
76 }
Lev Walkinfbfc7bc2006-08-28 02:45:44 +000077
78 /* Check value uniqueness as per 21.4 */
79 ret = asn1f_check_unique_expr_child(arg, v,
80 _compare_value, "value");
81 RET2RVAL(ret, r_value);
82 /* Check identifier uniqueness as per 21.5 */
83 ret = asn1f_check_unique_expr_child(arg, v, 0, "identifier");
84 RET2RVAL(ret, r_value);
Lev Walkinef4a32b2006-08-28 02:12:49 +000085 }
86
Lev Walkina0c92902006-08-28 02:24:24 +000087 return r_value;
Lev Walkinef4a32b2006-08-28 02:12:49 +000088}
89
90static int
Lev Walkinf15320b2004-06-03 03:38:44 +000091asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype) {
92 asn1p_expr_t *expr = arg->expr;
93 int r_value = 0;
94
Lev Walkin03850182005-03-10 10:02:50 +000095 DEBUG("(%s) for line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000096 expr->Identifier, expr->_lineno);
97
98 switch(expr->value->type) {
99 case ATV_UNPARSED:
100 /*
101 * Most definitely we have something like
102 * value BitStringType1 ::= { a, b, c }
103 * which could not be parsed by the LALR parser, mostly
104 * because it requires knowledge about BitStringType1
105 * during the parsing. So, here's a little hack: we create
106 * a buffer containing the full specification of a module,
107 * which contains some pre-defined INTEGER type with the
108 * opaque definition "{ a, b, c }" from the bit string.
109 */
110 if(asn1f_BS_unparsed_convert(arg, expr->value, ttype)) {
111 r_value = -1;
112 break;
113 }
114 /* Fall through: remove trailing zero bits */
115 case ATV_BITVECTOR:
116 asn1f_BS_remove_trailing_zero_bits(expr->value);
117 break;
118 default:
119 break;
120 }
121
122 return r_value;
123}
124
125static void
126asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value) {
127 int lmfb = -1; /* Last meaningful byte position */
128 int bits; /* Number of bits in the BIT STRING value */
129 int b;
130
131 assert(value->type == ATV_BITVECTOR);
132
133 bits = value->value.binary_vector.size_in_bits;
134 /*
135 * Figure out the rightmost meaningful byte.
136 */
137 for(b = 0; b < ((bits + 7) >> 3); b++) {
138 uint8_t uc = value->value.binary_vector.bits[b];
139 if(uc && b > lmfb)
140 lmfb = b;
141 }
142 if(lmfb == -1) {
143 bits = 0;
144 } else {
145 uint8_t uc;
146 uc = value->value.binary_vector.bits[lmfb];
147 bits = (lmfb+1) * 8;
148 /*
149 * Squeeze the bit string width until the rightmost
150 * bit is set.
151 */
152 for(; uc && (uc & 1) == 0; uc >>= 1)
153 bits--;
154 if(uc == 0) {
155 bits = lmfb * 8;
156 }
157 }
158 value->value.binary_vector.size_in_bits = bits;
159}
160
161static int
162asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype) {
163 asn1p_t *asn;
164 asn1p_module_t *mod;
165 asn1p_expr_t *V;
166 asn1p_expr_t *bit;
Lev Walkinb8108ec2004-09-29 13:17:17 +0000167 asn1c_integer_t aI;
Lev Walkinf15320b2004-06-03 03:38:44 +0000168 uint8_t *bitbuf;
169 int bits;
170 int psize;
171 char *p;
172 int ret;
173 int r_value = 0;
174
175 assert(value->type == ATV_UNPARSED);
176
Lev Walkinbe518fa2017-09-07 02:05:28 -0700177 psize = value->value.string.size + sizeof("M DEFINITIONS ::= BEGIN V ::= BIT STRING END") + 32;
Lev Walkinf15320b2004-06-03 03:38:44 +0000178 p = malloc(psize);
179 if(p == NULL)
180 return -1;
181
182 ret = snprintf(p, psize,
183 "M DEFINITIONS ::=\nBEGIN\n"
Lev Walkinbe518fa2017-09-07 02:05:28 -0700184 "V ::= #BIT STRING %s\n"
Lev Walkinf15320b2004-06-03 03:38:44 +0000185 "END\n",
186 value->value.string.buf
187 );
188 assert(ret < psize);
189 psize = ret;
190
Lev Walkinbe518fa2017-09-07 02:05:28 -0700191 asn = asn1p_parse_buffer(p, psize, arg->expr->module->source_file_name,
192 arg->expr->_lineno, A1P_EXTENDED_VALUES);
Lev Walkinf15320b2004-06-03 03:38:44 +0000193 free(p);
194 if(asn == NULL) {
195 FATAL("Cannot parse BIT STRING value %s "
196 "defined as %s at line %d",
197 arg->expr->Identifier,
198 value->value.string.buf,
199 arg->expr->_lineno
200 );
201 return -1;
202 }
203
204 mod = TQ_FIRST(&(asn->modules));
205 assert(mod);
206 V = TQ_FIRST(&(mod->members));
207 assert(V);
208 assert(strcmp(V->Identifier, "V") == 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000209
210 /*
211 * Simple loop just to fetch the maximal bit position
212 * out of the BIT STRING value defined as NamedBitList.
213 */
214 aI = -1;
215 TQ_FOR(bit, &(V->members), next) {
216 asn1p_expr_t *bitdef;
217 bitdef = asn1f_lookup_child(ttype, bit->Identifier);
218 if(bitdef && bitdef->value
219 && bitdef->value->type == ATV_INTEGER) {
220 if(bitdef->value->value.v_integer > aI)
221 aI = bitdef->value->value.v_integer;
222 }
223 }
224
225 if(aI > 1024 * 1024 * 8) { /* One megabyte */
226 FATAL("Unsupportedly large BIT STRING value \"%s\" "
227 "defined at line %d "
228 "(larger than 1MByte)",
229 arg->expr->Identifier,
230 arg->expr->_lineno
231 );
Lev Walkinf4b1d7f2006-09-12 05:19:28 +0000232 asn1p_delete(asn);
Lev Walkinf15320b2004-06-03 03:38:44 +0000233 return -1;
234 }
235
236 bits = aI + 1; /* Number of bits is more than a last bit position */
237 bitbuf = calloc(1, 1 + ((bits + 7) / 8));
238 if(bitbuf == NULL) {
Lev Walkinf4b1d7f2006-09-12 05:19:28 +0000239 asn1p_delete(asn);
Lev Walkinf15320b2004-06-03 03:38:44 +0000240 return -1;
241 }
242
243 TQ_FOR(bit, &(V->members), next) {
244 asn1p_expr_t *bitdef;
245 int set_bit_pos;
246
247 if(bit->value) {
248 WARNING("Identifier \"%s\" at line %d "
249 "must not have a value",
250 bit->Identifier, bit->_lineno);
251 RET2RVAL(1, r_value);
252 }
Lev Walkinbe518fa2017-09-07 02:05:28 -0700253 fprintf(stderr, "Referencing bit %s\n", bit->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000254 bitdef = asn1f_lookup_child(ttype, bit->Identifier);
255 if(bitdef == NULL) {
256 FATAL("Identifier \"%s\" at line %d is not defined "
257 "in the \"%s\" type definition at line %d",
258 bit->Identifier,
259 bit->_lineno,
260 ttype->Identifier,
261 ttype->_lineno
262 );
263 RET2RVAL(-1, r_value);
264 continue;
265 }
266 if(bitdef->value == NULL
267 || bitdef->value->type != ATV_INTEGER) {
268 FATAL("Broken identifier "
269 "\"%s\" at line %d "
270 "referenced by \"%s\" at line %d",
271 bitdef->Identifier,
272 bitdef->_lineno,
273 arg->expr->Identifier,
274 arg->expr->_lineno
275 );
276 RET2RVAL(-1, r_value);
277 continue;
278 }
279
280 assert(bitdef->value->value.v_integer < bits);
281 set_bit_pos = bitdef->value->value.v_integer;
282 bitbuf[set_bit_pos>>3] |= 1 << (7-(set_bit_pos % 8));
283 }
284
Lev Walkinf4b1d7f2006-09-12 05:19:28 +0000285 asn1p_delete(asn);
Lev Walkinf15320b2004-06-03 03:38:44 +0000286 free(value->value.string.buf);
287 value->type = ATV_BITVECTOR;
288 value->value.binary_vector.bits = bitbuf;
289 value->value.binary_vector.size_in_bits = bits;
290
291 return r_value;
292}