blob: c0286ff6bf23ed9f8ac4ec2bf2c8465c5b7f0ef8 [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
29uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
30 void *buf;
Lev Walkin375f0e92007-06-29 02:28:50 +000031 void *bptr;
Lev Walkin9218bc12007-06-27 04:09:37 +000032 ssize_t size;
Lev Walkin375f0e92007-06-29 02:28:50 +000033 size_t toGo;
Lev Walkin9218bc12007-06-27 04:09:37 +000034
Lev Walkin375f0e92007-06-29 02:28:50 +000035 ASN_DEBUG("Open type put %s ...", td->name);
36
Lev Walkin9218bc12007-06-27 04:09:37 +000037 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
38 if(size <= 0) return -1;
39
Lev Walkin375f0e92007-06-29 02:28:50 +000040 for(bptr = buf, toGo = size; toGo;) {
41 ssize_t maySave = uper_put_length(po, toGo);
Lev Walkin190419b2010-10-25 19:19:17 -070042 ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
43 (int)size, td->name, (int)maySave);
Lev Walkin9218bc12007-06-27 04:09:37 +000044 if(maySave < 0) break;
Lev Walkin375f0e92007-06-29 02:28:50 +000045 if(per_put_many_bits(po, bptr, maySave * 8)) break;
46 bptr = (char *)bptr + maySave;
47 toGo -= maySave;
Lev Walkin9218bc12007-06-27 04:09:37 +000048 }
49
Lev Walkin375f0e92007-06-29 02:28:50 +000050 FREEMEM(buf);
51 if(toGo) return -1;
52
Lev Walkinfe1ffaf2010-10-25 21:07:59 -070053 ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
54 td->name, (long)size);
Lev Walkin9218bc12007-06-27 04:09:37 +000055
56 return 0;
57}
58
Lev Walkin375f0e92007-06-29 02:28:50 +000059static asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -070060uper_open_type_get_simple(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -070061 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
Lev Walkin375f0e92007-06-29 02:28:50 +000062 asn_dec_rval_t rv;
63 ssize_t chunk_bytes;
64 int repeat;
65 uint8_t *buf = 0;
66 size_t bufLen = 0;
67 size_t bufSize = 0;
68 asn_per_data_t spd;
Lev Walkin55fdd992007-06-29 11:25:49 +000069 size_t padding;
Lev Walkin375f0e92007-06-29 02:28:50 +000070
Lev Walkin7c1dc052016-03-14 03:08:15 -070071 ASN__STACK_OVERFLOW_CHECK(ctx);
Lev Walkin375f0e92007-06-29 02:28:50 +000072
Lev Walkin7c97b882007-06-29 11:32:25 +000073 ASN_DEBUG("Getting open type %s...", td->name);
Lev Walkin375f0e92007-06-29 02:28:50 +000074
75 do {
76 chunk_bytes = uper_get_length(pd, -1, &repeat);
77 if(chunk_bytes < 0) {
78 FREEMEM(buf);
Lev Walkin7c1dc052016-03-14 03:08:15 -070079 ASN__DECODE_STARVED;
Lev Walkin375f0e92007-06-29 02:28:50 +000080 }
81 if(bufLen + chunk_bytes > bufSize) {
82 void *ptr;
83 bufSize = chunk_bytes + (bufSize << 2);
84 ptr = REALLOC(buf, bufSize);
85 if(!ptr) {
86 FREEMEM(buf);
Lev Walkin7c1dc052016-03-14 03:08:15 -070087 ASN__DECODE_FAILED;
Lev Walkin375f0e92007-06-29 02:28:50 +000088 }
89 buf = ptr;
90 }
91 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
92 FREEMEM(buf);
Lev Walkin7c1dc052016-03-14 03:08:15 -070093 ASN__DECODE_STARVED;
Lev Walkin375f0e92007-06-29 02:28:50 +000094 }
95 bufLen += chunk_bytes;
96 } while(repeat);
97
Lev Walkinfe1ffaf2010-10-25 21:07:59 -070098 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
99 (long)bufLen);
Lev Walkin55fdd992007-06-29 11:25:49 +0000100
Lev Walkin375f0e92007-06-29 02:28:50 +0000101 memset(&spd, 0, sizeof(spd));
102 spd.buffer = buf;
103 spd.nbits = bufLen << 3;
104
Lev Walkin69c73dc2012-02-21 02:15:08 -0800105 ASN_DEBUG_INDENT_ADD(+4);
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800106 rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
Lev Walkin69c73dc2012-02-21 02:15:08 -0800107 ASN_DEBUG_INDENT_ADD(-4);
Lev Walkin375f0e92007-06-29 02:28:50 +0000108
Lev Walkin49f510f2007-06-29 17:33:04 +0000109 if(rv.code == RC_OK) {
110 /* Check padding validity */
111 padding = spd.nbits - spd.nboff;
Lev Walkin190419b2010-10-25 19:19:17 -0700112 if ((padding < 8 ||
113 /* X.691#10.1.3 */
114 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
Lev Walkina6dd57a2010-10-24 22:03:14 -0700115 per_get_few_bits(&spd, padding) == 0) {
Lev Walkin49f510f2007-06-29 17:33:04 +0000116 /* Everything is cool */
117 FREEMEM(buf);
118 return rv;
119 }
120 FREEMEM(buf);
121 if(padding >= 8) {
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700122 ASN_DEBUG("Too large padding %d in open type", (int)padding);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700123 ASN__DECODE_FAILED;
Lev Walkin49f510f2007-06-29 17:33:04 +0000124 } else {
125 ASN_DEBUG("Non-zero padding");
Lev Walkin7c1dc052016-03-14 03:08:15 -0700126 ASN__DECODE_FAILED;
Lev Walkin49f510f2007-06-29 17:33:04 +0000127 }
128 } else {
129 FREEMEM(buf);
Lev Walkin80515f02007-06-29 23:23:05 +0000130 /* rv.code could be RC_WMORE, nonsense in this context */
131 rv.code = RC_FAIL; /* Noone would give us more */
Lev Walkin55fdd992007-06-29 11:25:49 +0000132 }
133
Lev Walkin375f0e92007-06-29 02:28:50 +0000134 return rv;
135}
136
Lev Walkin3f995632017-09-26 18:27:32 -0700137static asn_dec_rval_t CC_NOTUSED
Lev Walkinafbf2a92017-09-12 23:30:27 -0700138uper_open_type_get_complex(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin9218bc12007-06-27 04:09:37 +0000139 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
140 uper_ugot_key arg;
141 asn_dec_rval_t rv;
142 ssize_t padding;
143
Lev Walkin7c1dc052016-03-14 03:08:15 -0700144 ASN__STACK_OVERFLOW_CHECK(ctx);
Lev Walkin9218bc12007-06-27 04:09:37 +0000145
Lev Walkin375f0e92007-06-29 02:28:50 +0000146 ASN_DEBUG("Getting open type %s from %s", td->name,
Lev Walkin6cd0d562017-08-25 11:57:01 -0700147 asn_bit_data_string(pd));
Lev Walkin9218bc12007-06-27 04:09:37 +0000148 arg.oldpd = *pd;
149 arg.unclaimed = 0;
150 arg.ot_moved = 0;
151 arg.repeat = 1;
152 pd->refill = uper_ugot_refill;
153 pd->refill_key = &arg;
154 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
155 pd->moved = 0; /* This now counts the open type size in bits */
156
Lev Walkin69c73dc2012-02-21 02:15:08 -0800157 ASN_DEBUG_INDENT_ADD(+4);
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800158 rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
Lev Walkin69c73dc2012-02-21 02:15:08 -0800159 ASN_DEBUG_INDENT_ADD(-4);
Lev Walkin9218bc12007-06-27 04:09:37 +0000160
Lev Walkin375f0e92007-06-29 02:28:50 +0000161#define UPDRESTOREPD do { \
162 /* buffer and nboff are valid, preserve them. */ \
163 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
164 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
165 pd->refill = arg.oldpd.refill; \
166 pd->refill_key = arg.oldpd.refill_key; \
167 } while(0)
168
169 if(rv.code != RC_OK) {
170 UPDRESTOREPD;
171 return rv;
172 }
173
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700174 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
Lev Walkin6cd0d562017-08-25 11:57:01 -0700175 asn_bit_data_string(pd),
176 asn_bit_data_string(&arg.oldpd),
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700177 (int)arg.unclaimed, (int)arg.repeat);
Lev Walkin9218bc12007-06-27 04:09:37 +0000178
Lev Walkin9218bc12007-06-27 04:09:37 +0000179 padding = pd->moved % 8;
180 if(padding) {
181 int32_t pvalue;
182 if(padding > 7) {
183 ASN_DEBUG("Too large padding %d in open type",
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700184 (int)padding);
Lev Walkin9218bc12007-06-27 04:09:37 +0000185 rv.code = RC_FAIL;
Lev Walkin375f0e92007-06-29 02:28:50 +0000186 UPDRESTOREPD;
Lev Walkin9218bc12007-06-27 04:09:37 +0000187 return rv;
188 }
189 padding = 8 - padding;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700190 ASN_DEBUG("Getting padding of %d bits", (int)padding);
Lev Walkin9218bc12007-06-27 04:09:37 +0000191 pvalue = per_get_few_bits(pd, padding);
192 switch(pvalue) {
193 case -1:
194 ASN_DEBUG("Padding skip failed");
Lev Walkin375f0e92007-06-29 02:28:50 +0000195 UPDRESTOREPD;
Lev Walkin7c1dc052016-03-14 03:08:15 -0700196 ASN__DECODE_STARVED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000197 case 0: break;
198 default:
199 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700200 (int)padding, (int)pvalue);
Lev Walkin375f0e92007-06-29 02:28:50 +0000201 UPDRESTOREPD;
Lev Walkin7c1dc052016-03-14 03:08:15 -0700202 ASN__DECODE_FAILED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000203 }
204 }
Lev Walkin375f0e92007-06-29 02:28:50 +0000205 if(pd->nboff != pd->nbits) {
206 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
Lev Walkin6cd0d562017-08-25 11:57:01 -0700207 asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
Lev Walkin375f0e92007-06-29 02:28:50 +0000208 if(1) {
209 UPDRESTOREPD;
Lev Walkin7c1dc052016-03-14 03:08:15 -0700210 ASN__DECODE_FAILED;
Lev Walkin375f0e92007-06-29 02:28:50 +0000211 } else {
212 arg.unclaimed += pd->nbits - pd->nboff;
213 }
Lev Walkin9218bc12007-06-27 04:09:37 +0000214 }
215
216 /* Adjust pd back so it points to original data */
Lev Walkin375f0e92007-06-29 02:28:50 +0000217 UPDRESTOREPD;
Lev Walkin9218bc12007-06-27 04:09:37 +0000218
219 /* Skip data not consumed by the decoder */
Lev Walkin375f0e92007-06-29 02:28:50 +0000220 if(arg.unclaimed) {
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700221 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
Lev Walkin375f0e92007-06-29 02:28:50 +0000222 switch(per_skip_bits(pd, arg.unclaimed)) {
Lev Walkin9218bc12007-06-27 04:09:37 +0000223 case -1:
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700224 ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700225 ASN__DECODE_STARVED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000226 case 0:
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700227 ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
Lev Walkin375f0e92007-06-29 02:28:50 +0000228 break;
Lev Walkin9218bc12007-06-27 04:09:37 +0000229 default:
230 /* Padding must be blank */
231 ASN_DEBUG("Non-blank unconsumed padding");
Lev Walkin7c1dc052016-03-14 03:08:15 -0700232 ASN__DECODE_FAILED;
Lev Walkin9218bc12007-06-27 04:09:37 +0000233 }
Lev Walkin375f0e92007-06-29 02:28:50 +0000234 arg.unclaimed = 0;
Lev Walkin9218bc12007-06-27 04:09:37 +0000235 }
236
Lev Walkin9218bc12007-06-27 04:09:37 +0000237 if(arg.repeat) {
238 ASN_DEBUG("Not consumed the whole thing");
239 rv.code = RC_FAIL;
240 return rv;
241 }
242
243 return rv;
244}
245
Lev Walkin375f0e92007-06-29 02:28:50 +0000246
247asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700248uper_open_type_get(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700249 const asn_per_constraints_t *constraints, void **sptr,
250 asn_per_data_t *pd) {
251 return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
Lev Walkin375f0e92007-06-29 02:28:50 +0000252}
253
Lev Walkin9218bc12007-06-27 04:09:37 +0000254int
Lev Walkinafbf2a92017-09-12 23:30:27 -0700255uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
Lev Walkin9218bc12007-06-27 04:09:37 +0000256 asn_TYPE_descriptor_t s_td;
Lev Walkin75b6fe42017-08-27 01:03:22 -0700257 asn_TYPE_operation_t s_op;
Lev Walkin9218bc12007-06-27 04:09:37 +0000258 asn_dec_rval_t rv;
259
260 s_td.name = "<unknown extension>";
Lev Walkin75b6fe42017-08-27 01:03:22 -0700261 s_td.op = &s_op;
262 s_op.uper_decoder = uper_sot_suck;
Lev Walkin9218bc12007-06-27 04:09:37 +0000263
Lev Walkin375f0e92007-06-29 02:28:50 +0000264 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
Lev Walkin9218bc12007-06-27 04:09:37 +0000265 if(rv.code != RC_OK)
266 return -1;
267 else
268 return 0;
269}
270
271/*
272 * Internal functions.
273 */
274
275static asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700276uper_sot_suck(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700277 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
Lev Walkin9218bc12007-06-27 04:09:37 +0000278 asn_dec_rval_t rv;
279
Lev Walkin375f0e92007-06-29 02:28:50 +0000280 (void)ctx;
Lev Walkin9218bc12007-06-27 04:09:37 +0000281 (void)td;
282 (void)constraints;
283 (void)sptr;
284
285 while(per_get_few_bits(pd, 24) >= 0);
286
287 rv.code = RC_OK;
288 rv.consumed = pd->moved;
289
290 return rv;
291}
292
293static int
294uper_ugot_refill(asn_per_data_t *pd) {
295 uper_ugot_key *arg = pd->refill_key;
296 ssize_t next_chunk_bytes, next_chunk_bits;
297 ssize_t avail;
298
299 asn_per_data_t *oldpd = &arg->oldpd;
300
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700301 ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
302 (long)pd->moved, (long)oldpd->moved);
Lev Walkin9218bc12007-06-27 04:09:37 +0000303
304 /* Advance our position to where pd is */
305 oldpd->buffer = pd->buffer;
306 oldpd->nboff = pd->nboff;
307 oldpd->nbits -= pd->moved - arg->ot_moved;
308 oldpd->moved += pd->moved - arg->ot_moved;
309 arg->ot_moved = pd->moved;
310
311 if(arg->unclaimed) {
312 /* Refill the container */
313 if(per_get_few_bits(oldpd, 1))
314 return -1;
315 if(oldpd->nboff == 0) {
316 assert(0);
317 return -1;
318 }
319 pd->buffer = oldpd->buffer;
320 pd->nboff = oldpd->nboff - 1;
321 pd->nbits = oldpd->nbits;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700322 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
323 (long)pd->moved);
Lev Walkin9218bc12007-06-27 04:09:37 +0000324 return 0;
325 }
326
327 if(!arg->repeat) {
328 ASN_DEBUG("Want more but refill doesn't have it");
329 return -1;
330 }
331
332 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700333 ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
334 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
Lev Walkin9218bc12007-06-27 04:09:37 +0000335 if(next_chunk_bytes < 0) return -1;
336 if(next_chunk_bytes == 0) {
337 pd->refill = 0; /* No more refills, naturally */
338 assert(!arg->repeat); /* Implementation guarantee */
339 }
340 next_chunk_bits = next_chunk_bytes << 3;
341 avail = oldpd->nbits - oldpd->nboff;
342 if(avail >= next_chunk_bits) {
343 pd->nbits = oldpd->nboff + next_chunk_bits;
344 arg->unclaimed = 0;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700345 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
346 (long)next_chunk_bits, (long)oldpd->moved,
347 (long)oldpd->nboff, (long)oldpd->nbits,
348 (long)(oldpd->nbits - oldpd->nboff));
Lev Walkin9218bc12007-06-27 04:09:37 +0000349 } else {
350 pd->nbits = oldpd->nbits;
351 arg->unclaimed = next_chunk_bits - avail;
Lev Walkinfe1ffaf2010-10-25 21:07:59 -0700352 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
353 (long)avail, (long)next_chunk_bits,
354 (long)arg->unclaimed);
Lev Walkin9218bc12007-06-27 04:09:37 +0000355 }
356 pd->buffer = oldpd->buffer;
357 pd->nboff = oldpd->nboff;
Lev Walkin375f0e92007-06-29 02:28:50 +0000358 ASN_DEBUG("Refilled pd%s old%s",
Lev Walkin6cd0d562017-08-25 11:57:01 -0700359 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
Lev Walkin9218bc12007-06-27 04:09:37 +0000360 return 0;
361}
Lev Walkin375f0e92007-06-29 02:28:50 +0000362
363static int
364per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
365 int hasNonZeroBits = 0;
366 while(skip_nbits > 0) {
367 int skip;
Lev Walkinda161982013-03-20 03:35:21 -0700368
369 /* per_get_few_bits() is more efficient when nbits <= 24 */
370 if(skip_nbits < 24)
Lev Walkin375f0e92007-06-29 02:28:50 +0000371 skip = skip_nbits;
372 else
373 skip = 24;
374 skip_nbits -= skip;
375
376 switch(per_get_few_bits(pd, skip)) {
377 case -1: return -1; /* Starving */
378 case 0: continue; /* Skipped empty space */
379 default: hasNonZeroBits = 1; continue;
380 }
381 }
382 return hasNonZeroBits;
383}