1 /*
2  * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include "asn1/asn1c/asn_internal.h"
6 #include "asn1/asn1c/per_support.h"
7 #include "asn1/asn1c/constr_TYPE.h"
8 #include "asn1/asn1c/per_opentype.h"
9 
10 typedef struct uper_ugot_key {
11 	asn_per_data_t oldpd;	/* Old per data source */
12 	size_t unclaimed;
13 	size_t ot_moved;	/* Number of bits moved by OT processing */
14 	int repeat;
15 } uper_ugot_key;
16 
17 static int uper_ugot_refill(asn_per_data_t *pd);
18 static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
19 static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *,
20                                     const asn_TYPE_descriptor_t *td,
21                                     const asn_per_constraints_t *constraints,
22                                     void **sptr, asn_per_data_t *pd);
23 
24 /*
25  * Encode an "open type field".
26  * #10.1, #10.2
27  */
28 int
uper_open_type_put(const asn_TYPE_descriptor_t * td,const asn_per_constraints_t * constraints,const void * sptr,asn_per_outp_t * po)29 uper_open_type_put(const asn_TYPE_descriptor_t *td,
30                    const asn_per_constraints_t *constraints, const void *sptr,
31                    asn_per_outp_t *po) {
32     void *buf;
33     void *bptr;
34     ssize_t size;
35 
36     ASN_DEBUG("Open type put %s ...", td->name);
37 
38     size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
39     if(size <= 0) return -1;
40 
41     ASN_DEBUG("Open type put %s of length %" ASN_PRI_SSIZE " + overhead (1byte?)", td->name,
42               size);
43 
44     bptr = buf;
45     do {
46         int need_eom = 0;
47         ssize_t may_save = uper_put_length(po, size, &need_eom);
48         ASN_DEBUG("Prepending length %" ASN_PRI_SSIZE
49                   " to %s and allowing to save %" ASN_PRI_SSIZE,
50                   size, td->name, may_save);
51         if(may_save < 0) break;
52         if(per_put_many_bits(po, bptr, may_save * 8)) break;
53         bptr = (char *)bptr + may_save;
54         size -= may_save;
55         if(need_eom && uper_put_length(po, 0, 0)) {
56             FREEMEM(buf);
57             return -1;
58         }
59     } while(size);
60 
61     FREEMEM(buf);
62     if(size) return -1;
63 
64     return 0;
65 }
66 
67 static asn_dec_rval_t
uper_open_type_get_simple(const asn_codec_ctx_t * ctx,const asn_TYPE_descriptor_t * td,const asn_per_constraints_t * constraints,void ** sptr,asn_per_data_t * pd)68 uper_open_type_get_simple(const asn_codec_ctx_t *ctx,
69                           const asn_TYPE_descriptor_t *td,
70                           const asn_per_constraints_t *constraints, void **sptr,
71                           asn_per_data_t *pd) {
72     asn_dec_rval_t rv;
73 	ssize_t chunk_bytes;
74 	int repeat;
75 	uint8_t *buf = 0;
76 	size_t bufLen = 0;
77 	size_t bufSize = 0;
78 	asn_per_data_t spd;
79 	size_t padding;
80 
81 	ASN__STACK_OVERFLOW_CHECK(ctx);
82 
83 	ASN_DEBUG("Getting open type %s...", td->name);
84 
85 	do {
86 		chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
87 		if(chunk_bytes < 0) {
88 			FREEMEM(buf);
89 			ASN__DECODE_STARVED;
90 		}
91 		if(bufLen + chunk_bytes > bufSize) {
92 			void *ptr;
93 			bufSize = chunk_bytes + (bufSize << 2);
94 			ptr = REALLOC(buf, bufSize);
95 			if(!ptr) {
96 				FREEMEM(buf);
97 				ASN__DECODE_FAILED;
98 			}
99 			buf = ptr;
100 		}
101 		if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
102 			FREEMEM(buf);
103 			ASN__DECODE_STARVED;
104 		}
105 		bufLen += chunk_bytes;
106 	} while(repeat);
107 
108 	ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
109 		(long)bufLen);
110 
111 	memset(&spd, 0, sizeof(spd));
112 	spd.buffer = buf;
113 	spd.nbits = bufLen << 3;
114 
115 	ASN_DEBUG_INDENT_ADD(+4);
116 	rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
117 	ASN_DEBUG_INDENT_ADD(-4);
118 
119 	if(rv.code == RC_OK) {
120 		/* Check padding validity */
121 		padding = spd.nbits - spd.nboff;
122                 if ((padding < 8 ||
123 		/* X.691#10.1.3 */
124 		(spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
125                     per_get_few_bits(&spd, padding) == 0) {
126 			/* Everything is cool */
127 			FREEMEM(buf);
128 			return rv;
129 		}
130 		FREEMEM(buf);
131 		if(padding >= 8) {
132 			ASN_DEBUG("Too large padding %d in open type", (int)padding);
133 			ASN__DECODE_FAILED;
134 		} else {
135 			ASN_DEBUG("Non-zero padding");
136 			ASN__DECODE_FAILED;
137 		}
138 	} else {
139 		FREEMEM(buf);
140 		/* rv.code could be RC_WMORE, nonsense in this context */
141 		rv.code = RC_FAIL; /* Noone would give us more */
142 	}
143 
144 	return rv;
145 }
146 
147 static asn_dec_rval_t CC_NOTUSED
uper_open_type_get_complex(const asn_codec_ctx_t * ctx,const asn_TYPE_descriptor_t * td,asn_per_constraints_t * constraints,void ** sptr,asn_per_data_t * pd)148 uper_open_type_get_complex(const asn_codec_ctx_t *ctx,
149                            const asn_TYPE_descriptor_t *td,
150                            asn_per_constraints_t *constraints, void **sptr,
151                            asn_per_data_t *pd) {
152     uper_ugot_key arg;
153 	asn_dec_rval_t rv;
154 	ssize_t padding;
155 
156 	ASN__STACK_OVERFLOW_CHECK(ctx);
157 
158 	ASN_DEBUG("Getting open type %s from %s", td->name,
159 		asn_bit_data_string(pd));
160 	arg.oldpd = *pd;
161 	arg.unclaimed = 0;
162 	arg.ot_moved = 0;
163 	arg.repeat = 1;
164 	pd->refill = uper_ugot_refill;
165 	pd->refill_key = &arg;
166 	pd->nbits = pd->nboff;	/* 0 good bits at this point, will refill */
167 	pd->moved = 0;	/* This now counts the open type size in bits */
168 
169 	ASN_DEBUG_INDENT_ADD(+4);
170 	rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
171 	ASN_DEBUG_INDENT_ADD(-4);
172 
173 #define	UPDRESTOREPD	do {						\
174 	/* buffer and nboff are valid, preserve them. */		\
175 	pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved);	\
176 	pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved);	\
177 	pd->refill = arg.oldpd.refill;					\
178 	pd->refill_key = arg.oldpd.refill_key;				\
179   } while(0)
180 
181 	if(rv.code != RC_OK) {
182 		UPDRESTOREPD;
183 		return rv;
184 	}
185 
186 	ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
187 		asn_bit_data_string(pd),
188 		asn_bit_data_string(&arg.oldpd),
189 		(int)arg.unclaimed, (int)arg.repeat);
190 
191 	padding = pd->moved % 8;
192 	if(padding) {
193 		int32_t pvalue;
194 		if(padding > 7) {
195 			ASN_DEBUG("Too large padding %d in open type",
196 				(int)padding);
197 			rv.code = RC_FAIL;
198 			UPDRESTOREPD;
199 			return rv;
200 		}
201 		padding = 8 - padding;
202 		ASN_DEBUG("Getting padding of %d bits", (int)padding);
203 		pvalue = per_get_few_bits(pd, padding);
204 		switch(pvalue) {
205 		case -1:
206 			ASN_DEBUG("Padding skip failed");
207 			UPDRESTOREPD;
208 			ASN__DECODE_STARVED;
209 		case 0: break;
210 		default:
211 			ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
212 				(int)padding, (int)pvalue);
213 			UPDRESTOREPD;
214 			ASN__DECODE_FAILED;
215 		}
216 	}
217 	if(pd->nboff != pd->nbits) {
218 		ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
219 			asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
220 		if(1) {
221 			UPDRESTOREPD;
222 			ASN__DECODE_FAILED;
223 		} else {
224 			arg.unclaimed += pd->nbits - pd->nboff;
225 		}
226 	}
227 
228 	/* Adjust pd back so it points to original data */
229 	UPDRESTOREPD;
230 
231 	/* Skip data not consumed by the decoder */
232 	if(arg.unclaimed) {
233 		ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
234 		switch(per_skip_bits(pd, arg.unclaimed)) {
235 		case -1:
236 			ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
237 			ASN__DECODE_STARVED;
238 		case 0:
239 			ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
240 			break;
241 		default:
242 			/* Padding must be blank */
243 			ASN_DEBUG("Non-blank unconsumed padding");
244 			ASN__DECODE_FAILED;
245 		}
246 		arg.unclaimed = 0;
247 	}
248 
249 	if(arg.repeat) {
250 		ASN_DEBUG("Not consumed the whole thing");
251 		rv.code = RC_FAIL;
252 		return rv;
253 	}
254 
255 	return rv;
256 }
257 
258 
259 asn_dec_rval_t
uper_open_type_get(const asn_codec_ctx_t * ctx,const asn_TYPE_descriptor_t * td,const asn_per_constraints_t * constraints,void ** sptr,asn_per_data_t * pd)260 uper_open_type_get(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
261                    const asn_per_constraints_t *constraints, void **sptr,
262                    asn_per_data_t *pd) {
263     return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
264 }
265 
266 int
uper_open_type_skip(const asn_codec_ctx_t * ctx,asn_per_data_t * pd)267 uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
268 	asn_TYPE_descriptor_t s_td;
269     asn_TYPE_operation_t s_op;
270 	asn_dec_rval_t rv;
271 
272 	s_td.name = "<unknown extension>";
273 	s_td.op = &s_op;
274     s_op.uper_decoder = uper_sot_suck;
275 
276 	rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
277 	if(rv.code != RC_OK)
278 		return -1;
279 	else
280 		return 0;
281 }
282 
283 /*
284  * Internal functions.
285  */
286 
287 static asn_dec_rval_t
uper_sot_suck(const asn_codec_ctx_t * ctx,const asn_TYPE_descriptor_t * td,const asn_per_constraints_t * constraints,void ** sptr,asn_per_data_t * pd)288 uper_sot_suck(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
289               const asn_per_constraints_t *constraints, void **sptr,
290               asn_per_data_t *pd) {
291     asn_dec_rval_t rv;
292 
293 	(void)ctx;
294 	(void)td;
295 	(void)constraints;
296 	(void)sptr;
297 
298 	while(per_get_few_bits(pd, 24) >= 0);
299 
300 	rv.code = RC_OK;
301 	rv.consumed = pd->moved;
302 
303 	return rv;
304 }
305 
306 static int
uper_ugot_refill(asn_per_data_t * pd)307 uper_ugot_refill(asn_per_data_t *pd) {
308 	uper_ugot_key *arg = pd->refill_key;
309 	ssize_t next_chunk_bytes, next_chunk_bits;
310 	ssize_t avail;
311 
312 	asn_per_data_t *oldpd = &arg->oldpd;
313 
314 	ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
315 		(long)pd->moved, (long)oldpd->moved);
316 
317 	/* Advance our position to where pd is */
318 	oldpd->buffer = pd->buffer;
319 	oldpd->nboff  = pd->nboff;
320 	oldpd->nbits -= pd->moved - arg->ot_moved;
321 	oldpd->moved += pd->moved - arg->ot_moved;
322 	arg->ot_moved = pd->moved;
323 
324 	if(arg->unclaimed) {
325 		/* Refill the container */
326 		if(per_get_few_bits(oldpd, 1))
327 			return -1;
328 		if(oldpd->nboff == 0) {
329 			assert(0);
330 			return -1;
331 		}
332 		pd->buffer = oldpd->buffer;
333 		pd->nboff = oldpd->nboff - 1;
334 		pd->nbits = oldpd->nbits;
335 		ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
336 			(long)pd->moved);
337 		return 0;
338 	}
339 
340 	if(!arg->repeat) {
341 		ASN_DEBUG("Want more but refill doesn't have it");
342 		return -1;
343 	}
344 
345 	next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
346 	ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
347 		(long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
348 	if(next_chunk_bytes < 0) return -1;
349 	if(next_chunk_bytes == 0) {
350 		pd->refill = 0;	/* No more refills, naturally */
351 		assert(!arg->repeat);	/* Implementation guarantee */
352 	}
353 	next_chunk_bits = next_chunk_bytes << 3;
354 	avail = oldpd->nbits - oldpd->nboff;
355 	if(avail >= next_chunk_bits) {
356 		pd->nbits = oldpd->nboff + next_chunk_bits;
357 		arg->unclaimed = 0;
358 		ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
359 			(long)next_chunk_bits, (long)oldpd->moved,
360 			(long)oldpd->nboff, (long)oldpd->nbits,
361 			(long)(oldpd->nbits - oldpd->nboff));
362 	} else {
363 		pd->nbits = oldpd->nbits;
364 		arg->unclaimed = next_chunk_bits - avail;
365 		ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
366 			(long)avail, (long)next_chunk_bits,
367 			(long)arg->unclaimed);
368 	}
369 	pd->buffer = oldpd->buffer;
370 	pd->nboff = oldpd->nboff;
371 	ASN_DEBUG("Refilled pd%s old%s",
372 		asn_bit_data_string(pd), asn_bit_data_string(oldpd));
373 	return 0;
374 }
375 
376 static int
per_skip_bits(asn_per_data_t * pd,int skip_nbits)377 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
378 	int hasNonZeroBits = 0;
379 	while(skip_nbits > 0) {
380 		int skip;
381 
382 		/* per_get_few_bits() is more efficient when nbits <= 24 */
383 		if(skip_nbits < 24)
384 			skip = skip_nbits;
385 		else
386 			skip = 24;
387 		skip_nbits -= skip;
388 
389 		switch(per_get_few_bits(pd, skip)) {
390 		case -1: return -1;	/* Starving */
391 		case 0: continue;	/* Skipped empty space */
392 		default: hasNonZeroBits = 1; continue;
393 		}
394 	}
395 	return hasNonZeroBits;
396 }
397