blob: 984a96ddde8cf1dcb38561a79e4dda8df3345dad [file] [log] [blame]
Harald Welteec0e2172010-07-20 00:03:44 +02001/*
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 <asn_internal.h>
6#include <per_support.h>
7#include <constr_TYPE.h>
8#include <per_opentype.h>
9
10typedef 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
17static int uper_ugot_refill(asn_per_data_t *pd);
18static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
19static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
20
Harald Welteec0e2172010-07-20 00:03:44 +020021/*
22 * Encode an "open type field".
23 * #10.1, #10.2
24 */
25int
26uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
27 void *buf;
28 void *bptr;
29 ssize_t size;
30 size_t toGo;
31
32 ASN_DEBUG("Open type put %s ...", td->name);
33
34 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
35 if(size <= 0) return -1;
36
37 for(bptr = buf, toGo = size; toGo;) {
38 ssize_t maySave = uper_put_length(po, toGo);
Harald Welte41b85d52015-08-31 08:56:53 +020039 ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
40 (int)size, td->name, (int)maySave);
41 if(maySave < 0) break;
42 if(per_put_many_bits(po, bptr, maySave * 8)) break;
43 bptr = (char *)bptr + maySave;
44 toGo -= maySave;
45 }
46
47 FREEMEM(buf);
48 if(toGo) return -1;
49
50 ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
51 td->name, (long)size);
52
53 return 0;
54}
55
56int
57aper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
58 void *buf;
59 void *bptr;
60 ssize_t size;
61 size_t toGo;
62
63 ASN_DEBUG("Open type put %s ...", td->name);
64
65 size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
66 if(size <= 0) return -1;
67
68 for(bptr = buf, toGo = size; toGo;) {
69 ssize_t maySave = aper_put_length(po, -1, toGo);
Harald Welteec0e2172010-07-20 00:03:44 +020070 if(maySave < 0) break;
71 if(per_put_many_bits(po, bptr, maySave * 8)) break;
72 bptr = (char *)bptr + maySave;
73 toGo -= maySave;
74 }
75
76 FREEMEM(buf);
77 if(toGo) return -1;
78
79 ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)",
Harald Welte41b85d52015-08-31 08:56:53 +020080 td->name, size);
Harald Welteec0e2172010-07-20 00:03:44 +020081
82 return 0;
83}
84
85static asn_dec_rval_t
86uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
87 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
88 asn_dec_rval_t rv;
89 ssize_t chunk_bytes;
90 int repeat;
91 uint8_t *buf = 0;
92 size_t bufLen = 0;
93 size_t bufSize = 0;
94 asn_per_data_t spd;
95 size_t padding;
96
97 _ASN_STACK_OVERFLOW_CHECK(ctx);
98
99 ASN_DEBUG("Getting open type %s...", td->name);
100
101 do {
102 chunk_bytes = uper_get_length(pd, -1, &repeat);
103 if(chunk_bytes < 0) {
104 FREEMEM(buf);
105 _ASN_DECODE_STARVED;
106 }
107 if(bufLen + chunk_bytes > bufSize) {
108 void *ptr;
109 bufSize = chunk_bytes + (bufSize << 2);
110 ptr = REALLOC(buf, bufSize);
111 if(!ptr) {
112 FREEMEM(buf);
113 _ASN_DECODE_FAILED;
114 }
115 buf = ptr;
116 }
117 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
118 FREEMEM(buf);
119 _ASN_DECODE_STARVED;
120 }
121 bufLen += chunk_bytes;
122 } while(repeat);
123
Harald Welte41b85d52015-08-31 08:56:53 +0200124 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
125 (long)bufLen);
Harald Welteec0e2172010-07-20 00:03:44 +0200126
127 memset(&spd, 0, sizeof(spd));
128 spd.buffer = buf;
129 spd.nbits = bufLen << 3;
130
Harald Welte41b85d52015-08-31 08:56:53 +0200131 ASN_DEBUG_INDENT_ADD(+4);
Harald Welteec0e2172010-07-20 00:03:44 +0200132 rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
Harald Welte41b85d52015-08-31 08:56:53 +0200133 ASN_DEBUG_INDENT_ADD(-4);
Harald Welteec0e2172010-07-20 00:03:44 +0200134
135 if(rv.code == RC_OK) {
136 /* Check padding validity */
137 padding = spd.nbits - spd.nboff;
Harald Welte41b85d52015-08-31 08:56:53 +0200138 if ((padding < 8 ||
139 /* X.691#10.1.3 */
140 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
141 per_get_few_bits(&spd, padding) == 0) {
Harald Welteec0e2172010-07-20 00:03:44 +0200142 /* Everything is cool */
143 FREEMEM(buf);
144 return rv;
145 }
146 FREEMEM(buf);
147 if(padding >= 8) {
Harald Welte41b85d52015-08-31 08:56:53 +0200148 ASN_DEBUG("Too large padding %d in open type", (int)padding);
Harald Welteec0e2172010-07-20 00:03:44 +0200149 _ASN_DECODE_FAILED;
150 } else {
151 ASN_DEBUG("Non-zero padding");
152 _ASN_DECODE_FAILED;
153 }
154 } else {
155 FREEMEM(buf);
156 /* rv.code could be RC_WMORE, nonsense in this context */
157 rv.code = RC_FAIL; /* Noone would give us more */
158 }
159
160 return rv;
161}
162
163static asn_dec_rval_t GCC_NOTUSED
164uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
165 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
166 uper_ugot_key arg;
167 asn_dec_rval_t rv;
168 ssize_t padding;
169
170 _ASN_STACK_OVERFLOW_CHECK(ctx);
171
172 ASN_DEBUG("Getting open type %s from %s", td->name,
173 per_data_string(pd));
174 arg.oldpd = *pd;
175 arg.unclaimed = 0;
176 arg.ot_moved = 0;
177 arg.repeat = 1;
178 pd->refill = uper_ugot_refill;
179 pd->refill_key = &arg;
180 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
181 pd->moved = 0; /* This now counts the open type size in bits */
182
Harald Welte41b85d52015-08-31 08:56:53 +0200183 ASN_DEBUG_INDENT_ADD(+4);
Harald Welteec0e2172010-07-20 00:03:44 +0200184 rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
Harald Welte41b85d52015-08-31 08:56:53 +0200185 ASN_DEBUG_INDENT_ADD(-4);
Harald Welteec0e2172010-07-20 00:03:44 +0200186
187#define UPDRESTOREPD do { \
188 /* buffer and nboff are valid, preserve them. */ \
189 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
190 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
191 pd->refill = arg.oldpd.refill; \
192 pd->refill_key = arg.oldpd.refill_key; \
193 } while(0)
194
195 if(rv.code != RC_OK) {
196 UPDRESTOREPD;
197 return rv;
198 }
199
Harald Welte41b85d52015-08-31 08:56:53 +0200200 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
Harald Welteec0e2172010-07-20 00:03:44 +0200201 per_data_string(pd),
202 per_data_string(&arg.oldpd),
Harald Welte41b85d52015-08-31 08:56:53 +0200203 (int)arg.unclaimed, (int)arg.repeat);
Harald Welteec0e2172010-07-20 00:03:44 +0200204
205 padding = pd->moved % 8;
206 if(padding) {
207 int32_t pvalue;
208 if(padding > 7) {
209 ASN_DEBUG("Too large padding %d in open type",
Harald Welte41b85d52015-08-31 08:56:53 +0200210 (int)padding);
Harald Welteec0e2172010-07-20 00:03:44 +0200211 rv.code = RC_FAIL;
212 UPDRESTOREPD;
213 return rv;
214 }
215 padding = 8 - padding;
Harald Welte41b85d52015-08-31 08:56:53 +0200216 ASN_DEBUG("Getting padding of %d bits", (int)padding);
Harald Welteec0e2172010-07-20 00:03:44 +0200217 pvalue = per_get_few_bits(pd, padding);
218 switch(pvalue) {
219 case -1:
220 ASN_DEBUG("Padding skip failed");
221 UPDRESTOREPD;
222 _ASN_DECODE_STARVED;
223 case 0: break;
224 default:
225 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
Harald Welte41b85d52015-08-31 08:56:53 +0200226 (int)padding, (int)pvalue);
Harald Welteec0e2172010-07-20 00:03:44 +0200227 UPDRESTOREPD;
228 _ASN_DECODE_FAILED;
229 }
230 }
231 if(pd->nboff != pd->nbits) {
232 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
233 per_data_string(pd), per_data_string(&arg.oldpd));
234 if(1) {
235 UPDRESTOREPD;
236 _ASN_DECODE_FAILED;
237 } else {
238 arg.unclaimed += pd->nbits - pd->nboff;
239 }
240 }
241
242 /* Adjust pd back so it points to original data */
243 UPDRESTOREPD;
244
245 /* Skip data not consumed by the decoder */
Harald Welteec0e2172010-07-20 00:03:44 +0200246 if(arg.unclaimed) {
Harald Welte41b85d52015-08-31 08:56:53 +0200247 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
Harald Welteec0e2172010-07-20 00:03:44 +0200248 switch(per_skip_bits(pd, arg.unclaimed)) {
249 case -1:
Harald Welte41b85d52015-08-31 08:56:53 +0200250 ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
Harald Welteec0e2172010-07-20 00:03:44 +0200251 _ASN_DECODE_STARVED;
252 case 0:
Harald Welte41b85d52015-08-31 08:56:53 +0200253 ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
Harald Welteec0e2172010-07-20 00:03:44 +0200254 break;
255 default:
256 /* Padding must be blank */
257 ASN_DEBUG("Non-blank unconsumed padding");
258 _ASN_DECODE_FAILED;
259 }
260 arg.unclaimed = 0;
261 }
262
263 if(arg.repeat) {
264 ASN_DEBUG("Not consumed the whole thing");
265 rv.code = RC_FAIL;
266 return rv;
267 }
268
269 return rv;
270}
271
272
273asn_dec_rval_t
274uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
275 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
276
Harald Welte41b85d52015-08-31 08:56:53 +0200277 return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
Harald Welteec0e2172010-07-20 00:03:44 +0200278}
279
280int
281uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
282 asn_TYPE_descriptor_t s_td;
283 asn_dec_rval_t rv;
284
285 s_td.name = "<unknown extension>";
286 s_td.uper_decoder = uper_sot_suck;
287
288 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
289 if(rv.code != RC_OK)
290 return -1;
291 else
292 return 0;
293}
294
295/*
296 * Internal functions.
297 */
298
299static asn_dec_rval_t
300uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
301 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
302 asn_dec_rval_t rv;
303
304 (void)ctx;
305 (void)td;
306 (void)constraints;
307 (void)sptr;
308
309 while(per_get_few_bits(pd, 24) >= 0);
310
311 rv.code = RC_OK;
312 rv.consumed = pd->moved;
313
314 return rv;
315}
316
317static int
318uper_ugot_refill(asn_per_data_t *pd) {
319 uper_ugot_key *arg = pd->refill_key;
320 ssize_t next_chunk_bytes, next_chunk_bits;
321 ssize_t avail;
322
323 asn_per_data_t *oldpd = &arg->oldpd;
324
Harald Welte41b85d52015-08-31 08:56:53 +0200325 ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
326 (long)pd->moved, (long)oldpd->moved);
Harald Welteec0e2172010-07-20 00:03:44 +0200327
328 /* Advance our position to where pd is */
329 oldpd->buffer = pd->buffer;
330 oldpd->nboff = pd->nboff;
331 oldpd->nbits -= pd->moved - arg->ot_moved;
332 oldpd->moved += pd->moved - arg->ot_moved;
333 arg->ot_moved = pd->moved;
334
335 if(arg->unclaimed) {
336 /* Refill the container */
337 if(per_get_few_bits(oldpd, 1))
338 return -1;
339 if(oldpd->nboff == 0) {
340 assert(0);
341 return -1;
342 }
343 pd->buffer = oldpd->buffer;
344 pd->nboff = oldpd->nboff - 1;
345 pd->nbits = oldpd->nbits;
Harald Welte41b85d52015-08-31 08:56:53 +0200346 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
347 (long)pd->moved);
Harald Welteec0e2172010-07-20 00:03:44 +0200348 return 0;
349 }
350
351 if(!arg->repeat) {
352 ASN_DEBUG("Want more but refill doesn't have it");
353 return -1;
354 }
355
356 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
Harald Welte41b85d52015-08-31 08:56:53 +0200357 ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
358 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
Harald Welteec0e2172010-07-20 00:03:44 +0200359 if(next_chunk_bytes < 0) return -1;
360 if(next_chunk_bytes == 0) {
361 pd->refill = 0; /* No more refills, naturally */
362 assert(!arg->repeat); /* Implementation guarantee */
363 }
364 next_chunk_bits = next_chunk_bytes << 3;
365 avail = oldpd->nbits - oldpd->nboff;
366 if(avail >= next_chunk_bits) {
367 pd->nbits = oldpd->nboff + next_chunk_bits;
368 arg->unclaimed = 0;
Harald Welte41b85d52015-08-31 08:56:53 +0200369 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
370 (long)next_chunk_bits, (long)oldpd->moved,
371 (long)oldpd->nboff, (long)oldpd->nbits,
372 (long)(oldpd->nbits - oldpd->nboff));
Harald Welteec0e2172010-07-20 00:03:44 +0200373 } else {
374 pd->nbits = oldpd->nbits;
375 arg->unclaimed = next_chunk_bits - avail;
Harald Welte41b85d52015-08-31 08:56:53 +0200376 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
377 (long)avail, (long)next_chunk_bits,
378 (long)arg->unclaimed);
Harald Welteec0e2172010-07-20 00:03:44 +0200379 }
380 pd->buffer = oldpd->buffer;
381 pd->nboff = oldpd->nboff;
382 ASN_DEBUG("Refilled pd%s old%s",
383 per_data_string(pd), per_data_string(oldpd));
384 return 0;
385}
386
387static int
388per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
389 int hasNonZeroBits = 0;
390 while(skip_nbits > 0) {
391 int skip;
Harald Welte41b85d52015-08-31 08:56:53 +0200392
393 /* per_get_few_bits() is more efficient when nbits <= 24 */
394 if(skip_nbits < 24)
Harald Welteec0e2172010-07-20 00:03:44 +0200395 skip = skip_nbits;
396 else
397 skip = 24;
398 skip_nbits -= skip;
399
400 switch(per_get_few_bits(pd, skip)) {
401 case -1: return -1; /* Starving */
402 case 0: continue; /* Skipped empty space */
403 default: hasNonZeroBits = 1; continue;
404 }
405 }
406 return hasNonZeroBits;
407}