blob: 70a1b440ed6fe2e720077e66ffa376dcda9f03af [file] [log] [blame]
Lev Walkin9218bc12007-06-27 04:09:37 +00001/*
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);
Lev Walkin375f0e92007-06-29 02:28:50 +000018static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
Lev Walkinafbf2a92017-09-12 23:30:27 -070019static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *,
Lev Walkin494fb702017-08-07 20:07:00 -070020 asn_TYPE_descriptor_t *td,
21 const asn_per_constraints_t *constraints,
22 void **sptr, asn_per_data_t *pd);
Lev Walkin9218bc12007-06-27 04:09:37 +000023
24/*
Lev Walkin375f0e92007-06-29 02:28:50 +000025 * Encode an "open type field".
Lev Walkin9218bc12007-06-27 04:09:37 +000026 * #10.1, #10.2
27 */
28int
Lev Walkina5972be2017-09-29 23:15:58 -070029uper_open_type_put(asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
Lev Walkin5d947a82017-10-03 01:04:03 -070030 void *buf;
31 void *bptr;
32 ssize_t size;
Lev Walkin9218bc12007-06-27 04:09:37 +000033
Lev Walkin5d947a82017-10-03 01:04:03 -070034 ASN_DEBUG("Open type put %s ...", td->name);
Lev Walkin375f0e92007-06-29 02:28:50 +000035
Lev Walkin5d947a82017-10-03 01:04:03 -070036 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
37 if(size <= 0) return -1;
Lev Walkin9218bc12007-06-27 04:09:37 +000038
Lev Walkin5d947a82017-10-03 01:04:03 -070039 ASN_DEBUG("Open type put %s of length %zd + overhead (1byte?)", td->name,
40 size);
Lev Walkin9218bc12007-06-27 04:09:37 +000041
Lev Walkin5d947a82017-10-03 01:04:03 -070042 bptr = buf;
43 do {
44 int need_eom = 0;
45 ssize_t maySave = uper_put_length(po, size, &need_eom);
46 ASN_DEBUG("Prepending length %zd to %s and allowing to save %d", size,
47 td->name, (int)maySave);
48 if(maySave < 0) break;
49 if(per_put_many_bits(po, bptr, maySave * 8)) break;
50 bptr = (char *)bptr + maySave;
51 size -= maySave;
52 if(need_eom && uper_put_length(po, 0, 0)) {
53 FREEMEM(buf);
54 return -1;
55 }
56 } while(size);
Lev Walkin375f0e92007-06-29 02:28:50 +000057
Lev Walkin5d947a82017-10-03 01:04:03 -070058 FREEMEM(buf);
59 if(size) return -1;
Lev Walkin9218bc12007-06-27 04:09:37 +000060
Lev Walkin5d947a82017-10-03 01:04:03 -070061 return 0;
Lev Walkin9218bc12007-06-27 04:09:37 +000062}
63
Lev Walkin375f0e92007-06-29 02:28:50 +000064static asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -070065uper_open_type_get_simple(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -070066 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
Lev Walkin375f0e92007-06-29 02:28:50 +000067 asn_dec_rval_t rv;
68 ssize_t chunk_bytes;
69 int repeat;
70 uint8_t *buf = 0;
71 size_t bufLen = 0;
72 size_t bufSize = 0;
73 asn_per_data_t spd;
Lev Walkin55fdd992007-06-29 11:25:49 +000074 size_t padding;
Lev Walkin375f0e92007-06-29 02:28:50 +000075
Lev Walkin7c1dc052016-03-14 03:08:15 -070076 ASN__STACK_OVERFLOW_CHECK(ctx);
Lev Walkin375f0e92007-06-29 02:28:50 +000077
Lev Walkin7c97b882007-06-29 11:32:25 +000078 ASN_DEBUG("Getting open type %s...", td->name);
Lev Walkin375f0e92007-06-29 02:28:50 +000079
80 do {
Lev Walkin9d1b45f2017-10-01 17:04:48 -070081 chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
Lev Walkin375f0e92007-06-29 02:28:50 +000082 if(chunk_bytes < 0) {
83 FREEMEM(buf);
Lev Walkin7c1dc052016-03-14 03:08:15 -070084 ASN__DECODE_STARVED;
Lev Walkin375f0e92007-06-29 02:28:50 +000085 }
86 if(bufLen + chunk_bytes > bufSize) {
87 void *ptr;
88 bufSize = chunk_bytes + (bufSize << 2);
89 ptr = REALLOC(buf, bufSize);
90 if(!ptr) {
91 FREEMEM(buf);
Lev Walkin7c1dc052016-03-14 03:08:15 -070092 ASN__DECODE_FAILED;
Lev Walkin375f0e92007-06-29 02:28:50 +000093 }
94 buf = ptr;
95 }
96 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
97 FREEMEM(buf);
Lev Walkin7c1dc052016-03-14 03:08:15 -070098 ASN__DECODE_STARVED;
Lev Walkin375f0e92007-06-29 02:28:50 +000099 }
100 bufLen += chunk_bytes;
101 } while(repeat);
102
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700103 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
104 (long)bufLen);
Lev Walkin55fdd992007-06-29 11:25:49 +0000105
Lev Walkin375f0e92007-06-29 02:28:50 +0000106 memset(&spd, 0, sizeof(spd));
107 spd.buffer = buf;
108 spd.nbits = bufLen << 3;
109
Lev Walkin69c73dc2012-02-21 02:15:08 -0800110 ASN_DEBUG_INDENT_ADD(+4);
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800111 rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
Lev Walkin69c73dc2012-02-21 02:15:08 -0800112 ASN_DEBUG_INDENT_ADD(-4);
Lev Walkin375f0e92007-06-29 02:28:50 +0000113
Lev Walkin49f510f2007-06-29 17:33:04 +0000114 if(rv.code == RC_OK) {
115 /* Check padding validity */
116 padding = spd.nbits - spd.nboff;
Lev Walkin190419b2010-10-25 19:19:17 -0700117 if ((padding < 8 ||
118 /* X.691#10.1.3 */
119 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
Lev Walkina6dd57a2010-10-24 22:03:14 -0700120 per_get_few_bits(&spd, padding) == 0) {
Lev Walkin49f510f2007-06-29 17:33:04 +0000121 /* Everything is cool */
122 FREEMEM(buf);
123 return rv;
124 }
125 FREEMEM(buf);
126 if(padding >= 8) {
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700127 ASN_DEBUG("Too large padding %d in open type", (int)padding);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700128 ASN__DECODE_FAILED;
Lev Walkin49f510f2007-06-29 17:33:04 +0000129 } else {
130 ASN_DEBUG("Non-zero padding");
Lev Walkin7c1dc052016-03-14 03:08:15 -0700131 ASN__DECODE_FAILED;
Lev Walkin49f510f2007-06-29 17:33:04 +0000132 }
133 } else {
134 FREEMEM(buf);
Lev Walkin80515f02007-06-29 23:23:05 +0000135 /* rv.code could be RC_WMORE, nonsense in this context */
136 rv.code = RC_FAIL; /* Noone would give us more */
Lev Walkin55fdd992007-06-29 11:25:49 +0000137 }
138
Lev Walkin375f0e92007-06-29 02:28:50 +0000139 return rv;
140}
141
Lev Walkin3f995632017-09-26 18:27:32 -0700142static asn_dec_rval_t CC_NOTUSED
Lev Walkinafbf2a92017-09-12 23:30:27 -0700143uper_open_type_get_complex(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin9218bc12007-06-27 04:09:37 +0000144 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
145 uper_ugot_key arg;
146 asn_dec_rval_t rv;
147 ssize_t padding;
148
Lev Walkin7c1dc052016-03-14 03:08:15 -0700149 ASN__STACK_OVERFLOW_CHECK(ctx);
Lev Walkin9218bc12007-06-27 04:09:37 +0000150
Lev Walkin375f0e92007-06-29 02:28:50 +0000151 ASN_DEBUG("Getting open type %s from %s", td->name,
Lev Walkin6cd0d562017-08-25 11:57:01 -0700152 asn_bit_data_string(pd));
Lev Walkin9218bc12007-06-27 04:09:37 +0000153 arg.oldpd = *pd;
154 arg.unclaimed = 0;
155 arg.ot_moved = 0;
156 arg.repeat = 1;
157 pd->refill = uper_ugot_refill;
158 pd->refill_key = &arg;
159 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
160 pd->moved = 0; /* This now counts the open type size in bits */
161
Lev Walkin69c73dc2012-02-21 02:15:08 -0800162 ASN_DEBUG_INDENT_ADD(+4);
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800163 rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
Lev Walkin69c73dc2012-02-21 02:15:08 -0800164 ASN_DEBUG_INDENT_ADD(-4);
Lev Walkin9218bc12007-06-27 04:09:37 +0000165
Lev Walkin375f0e92007-06-29 02:28:50 +0000166#define UPDRESTOREPD do { \
167 /* buffer and nboff are valid, preserve them. */ \
168 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
169 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
170 pd->refill = arg.oldpd.refill; \
171 pd->refill_key = arg.oldpd.refill_key; \
172 } while(0)
173
174 if(rv.code != RC_OK) {
175 UPDRESTOREPD;
176 return rv;
177 }
178
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700179 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
Lev Walkin6cd0d562017-08-25 11:57:01 -0700180 asn_bit_data_string(pd),
181 asn_bit_data_string(&arg.oldpd),
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700182 (int)arg.unclaimed, (int)arg.repeat);
Lev Walkin9218bc12007-06-27 04:09:37 +0000183
Lev Walkin9218bc12007-06-27 04:09:37 +0000184 padding = pd->moved % 8;
185 if(padding) {
186 int32_t pvalue;
187 if(padding > 7) {
188 ASN_DEBUG("Too large padding %d in open type",
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700189 (int)padding);
Lev Walkin9218bc12007-06-27 04:09:37 +0000190 rv.code = RC_FAIL;
Lev Walkin375f0e92007-06-29 02:28:50 +0000191 UPDRESTOREPD;
Lev Walkin9218bc12007-06-27 04:09:37 +0000192 return rv;
193 }
194 padding = 8 - padding;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700195 ASN_DEBUG("Getting padding of %d bits", (int)padding);
Lev Walkin9218bc12007-06-27 04:09:37 +0000196 pvalue = per_get_few_bits(pd, padding);
197 switch(pvalue) {
198 case -1:
199 ASN_DEBUG("Padding skip failed");
Lev Walkin375f0e92007-06-29 02:28:50 +0000200 UPDRESTOREPD;
Lev Walkin7c1dc052016-03-14 03:08:15 -0700201 ASN__DECODE_STARVED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000202 case 0: break;
203 default:
204 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700205 (int)padding, (int)pvalue);
Lev Walkin375f0e92007-06-29 02:28:50 +0000206 UPDRESTOREPD;
Lev Walkin7c1dc052016-03-14 03:08:15 -0700207 ASN__DECODE_FAILED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000208 }
209 }
Lev Walkin375f0e92007-06-29 02:28:50 +0000210 if(pd->nboff != pd->nbits) {
211 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
Lev Walkin6cd0d562017-08-25 11:57:01 -0700212 asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
Lev Walkin375f0e92007-06-29 02:28:50 +0000213 if(1) {
214 UPDRESTOREPD;
Lev Walkin7c1dc052016-03-14 03:08:15 -0700215 ASN__DECODE_FAILED;
Lev Walkin375f0e92007-06-29 02:28:50 +0000216 } else {
217 arg.unclaimed += pd->nbits - pd->nboff;
218 }
Lev Walkin9218bc12007-06-27 04:09:37 +0000219 }
220
221 /* Adjust pd back so it points to original data */
Lev Walkin375f0e92007-06-29 02:28:50 +0000222 UPDRESTOREPD;
Lev Walkin9218bc12007-06-27 04:09:37 +0000223
224 /* Skip data not consumed by the decoder */
Lev Walkin375f0e92007-06-29 02:28:50 +0000225 if(arg.unclaimed) {
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700226 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
Lev Walkin375f0e92007-06-29 02:28:50 +0000227 switch(per_skip_bits(pd, arg.unclaimed)) {
Lev Walkin9218bc12007-06-27 04:09:37 +0000228 case -1:
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700229 ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700230 ASN__DECODE_STARVED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000231 case 0:
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700232 ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
Lev Walkin375f0e92007-06-29 02:28:50 +0000233 break;
Lev Walkin9218bc12007-06-27 04:09:37 +0000234 default:
235 /* Padding must be blank */
236 ASN_DEBUG("Non-blank unconsumed padding");
Lev Walkin7c1dc052016-03-14 03:08:15 -0700237 ASN__DECODE_FAILED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000238 }
Lev Walkin375f0e92007-06-29 02:28:50 +0000239 arg.unclaimed = 0;
Lev Walkin9218bc12007-06-27 04:09:37 +0000240 }
241
Lev Walkin9218bc12007-06-27 04:09:37 +0000242 if(arg.repeat) {
243 ASN_DEBUG("Not consumed the whole thing");
244 rv.code = RC_FAIL;
245 return rv;
246 }
247
248 return rv;
249}
250
Lev Walkin375f0e92007-06-29 02:28:50 +0000251
252asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700253uper_open_type_get(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700254 const asn_per_constraints_t *constraints, void **sptr,
255 asn_per_data_t *pd) {
256 return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
Lev Walkin375f0e92007-06-29 02:28:50 +0000257}
258
Lev Walkin9218bc12007-06-27 04:09:37 +0000259int
Lev Walkinafbf2a92017-09-12 23:30:27 -0700260uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
Lev Walkin9218bc12007-06-27 04:09:37 +0000261 asn_TYPE_descriptor_t s_td;
Lev Walkin75b6fe42017-08-27 01:03:22 -0700262 asn_TYPE_operation_t s_op;
Lev Walkin9218bc12007-06-27 04:09:37 +0000263 asn_dec_rval_t rv;
264
265 s_td.name = "<unknown extension>";
Lev Walkin75b6fe42017-08-27 01:03:22 -0700266 s_td.op = &s_op;
267 s_op.uper_decoder = uper_sot_suck;
Lev Walkin9218bc12007-06-27 04:09:37 +0000268
Lev Walkin375f0e92007-06-29 02:28:50 +0000269 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
Lev Walkin9218bc12007-06-27 04:09:37 +0000270 if(rv.code != RC_OK)
271 return -1;
272 else
273 return 0;
274}
275
276/*
277 * Internal functions.
278 */
279
280static asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700281uper_sot_suck(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700282 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
Lev Walkin9218bc12007-06-27 04:09:37 +0000283 asn_dec_rval_t rv;
284
Lev Walkin375f0e92007-06-29 02:28:50 +0000285 (void)ctx;
Lev Walkin9218bc12007-06-27 04:09:37 +0000286 (void)td;
287 (void)constraints;
288 (void)sptr;
289
290 while(per_get_few_bits(pd, 24) >= 0);
291
292 rv.code = RC_OK;
293 rv.consumed = pd->moved;
294
295 return rv;
296}
297
298static int
299uper_ugot_refill(asn_per_data_t *pd) {
300 uper_ugot_key *arg = pd->refill_key;
301 ssize_t next_chunk_bytes, next_chunk_bits;
302 ssize_t avail;
303
304 asn_per_data_t *oldpd = &arg->oldpd;
305
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700306 ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
307 (long)pd->moved, (long)oldpd->moved);
Lev Walkin9218bc12007-06-27 04:09:37 +0000308
309 /* Advance our position to where pd is */
310 oldpd->buffer = pd->buffer;
311 oldpd->nboff = pd->nboff;
312 oldpd->nbits -= pd->moved - arg->ot_moved;
313 oldpd->moved += pd->moved - arg->ot_moved;
314 arg->ot_moved = pd->moved;
315
316 if(arg->unclaimed) {
317 /* Refill the container */
318 if(per_get_few_bits(oldpd, 1))
319 return -1;
320 if(oldpd->nboff == 0) {
321 assert(0);
322 return -1;
323 }
324 pd->buffer = oldpd->buffer;
325 pd->nboff = oldpd->nboff - 1;
326 pd->nbits = oldpd->nbits;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700327 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
328 (long)pd->moved);
Lev Walkin9218bc12007-06-27 04:09:37 +0000329 return 0;
330 }
331
332 if(!arg->repeat) {
333 ASN_DEBUG("Want more but refill doesn't have it");
334 return -1;
335 }
336
Lev Walkin9d1b45f2017-10-01 17:04:48 -0700337 next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700338 ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
339 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
Lev Walkin9218bc12007-06-27 04:09:37 +0000340 if(next_chunk_bytes < 0) return -1;
341 if(next_chunk_bytes == 0) {
342 pd->refill = 0; /* No more refills, naturally */
343 assert(!arg->repeat); /* Implementation guarantee */
344 }
345 next_chunk_bits = next_chunk_bytes << 3;
346 avail = oldpd->nbits - oldpd->nboff;
347 if(avail >= next_chunk_bits) {
348 pd->nbits = oldpd->nboff + next_chunk_bits;
349 arg->unclaimed = 0;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700350 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
351 (long)next_chunk_bits, (long)oldpd->moved,
352 (long)oldpd->nboff, (long)oldpd->nbits,
353 (long)(oldpd->nbits - oldpd->nboff));
Lev Walkin9218bc12007-06-27 04:09:37 +0000354 } else {
355 pd->nbits = oldpd->nbits;
356 arg->unclaimed = next_chunk_bits - avail;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700357 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
358 (long)avail, (long)next_chunk_bits,
359 (long)arg->unclaimed);
Lev Walkin9218bc12007-06-27 04:09:37 +0000360 }
361 pd->buffer = oldpd->buffer;
362 pd->nboff = oldpd->nboff;
Lev Walkin375f0e92007-06-29 02:28:50 +0000363 ASN_DEBUG("Refilled pd%s old%s",
Lev Walkin6cd0d562017-08-25 11:57:01 -0700364 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
Lev Walkin9218bc12007-06-27 04:09:37 +0000365 return 0;
366}
Lev Walkin375f0e92007-06-29 02:28:50 +0000367
368static int
369per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
370 int hasNonZeroBits = 0;
371 while(skip_nbits > 0) {
372 int skip;
Lev Walkinda161982013-03-20 03:35:21 -0700373
374 /* per_get_few_bits() is more efficient when nbits <= 24 */
375 if(skip_nbits < 24)
Lev Walkin375f0e92007-06-29 02:28:50 +0000376 skip = skip_nbits;
377 else
378 skip = 24;
379 skip_nbits -= skip;
380
381 switch(per_get_few_bits(pd, skip)) {
382 case -1: return -1; /* Starving */
383 case 0: continue; /* Skipped empty space */
384 default: hasNonZeroBits = 1; continue;
385 }
386 }
387 return hasNonZeroBits;
388}