Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 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 <asn_internal.h> |
| 6 | #include <per_support.h> |
| 7 | #include <constr_TYPE.h> |
| 8 | #include <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); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 18 | static int per_skip_bits(asn_per_data_t *pd, int skip_nbits); |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 19 | static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *, |
Lev Walkin | 494fb70 | 2017-08-07 20:07:00 -0700 | [diff] [blame] | 20 | asn_TYPE_descriptor_t *td, |
| 21 | const asn_per_constraints_t *constraints, |
| 22 | void **sptr, asn_per_data_t *pd); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 23 | |
| 24 | /* |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 25 | * Encode an "open type field". |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 26 | * #10.1, #10.2 |
| 27 | */ |
| 28 | int |
Lev Walkin | a5972be | 2017-09-29 23:15:58 -0700 | [diff] [blame] | 29 | uper_open_type_put(asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 30 | void *buf; |
| 31 | void *bptr; |
| 32 | ssize_t size; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 33 | |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 34 | ASN_DEBUG("Open type put %s ...", td->name); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 35 | |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 36 | size = uper_encode_to_new_buffer(td, constraints, sptr, &buf); |
| 37 | if(size <= 0) return -1; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 38 | |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 39 | ASN_DEBUG("Open type put %s of length %zd + overhead (1byte?)", td->name, |
| 40 | size); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 41 | |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 42 | 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 Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 57 | |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 58 | FREEMEM(buf); |
| 59 | if(size) return -1; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 60 | |
Lev Walkin | 5d947a8 | 2017-10-03 01:04:03 -0700 | [diff] [blame] | 61 | return 0; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 62 | } |
| 63 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 64 | static asn_dec_rval_t |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 65 | uper_open_type_get_simple(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, |
Lev Walkin | 494fb70 | 2017-08-07 20:07:00 -0700 | [diff] [blame] | 66 | const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 67 | 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 Walkin | 55fdd99 | 2007-06-29 11:25:49 +0000 | [diff] [blame] | 74 | size_t padding; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 75 | |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 76 | ASN__STACK_OVERFLOW_CHECK(ctx); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 77 | |
Lev Walkin | 7c97b88 | 2007-06-29 11:32:25 +0000 | [diff] [blame] | 78 | ASN_DEBUG("Getting open type %s...", td->name); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 79 | |
| 80 | do { |
Lev Walkin | 9d1b45f | 2017-10-01 17:04:48 -0700 | [diff] [blame] | 81 | chunk_bytes = uper_get_length(pd, -1, 0, &repeat); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 82 | if(chunk_bytes < 0) { |
| 83 | FREEMEM(buf); |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 84 | ASN__DECODE_STARVED; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 85 | } |
| 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 Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 92 | ASN__DECODE_FAILED; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 93 | } |
| 94 | buf = ptr; |
| 95 | } |
| 96 | if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) { |
| 97 | FREEMEM(buf); |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 98 | ASN__DECODE_STARVED; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 99 | } |
| 100 | bufLen += chunk_bytes; |
| 101 | } while(repeat); |
| 102 | |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 103 | ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name, |
| 104 | (long)bufLen); |
Lev Walkin | 55fdd99 | 2007-06-29 11:25:49 +0000 | [diff] [blame] | 105 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 106 | memset(&spd, 0, sizeof(spd)); |
| 107 | spd.buffer = buf; |
| 108 | spd.nbits = bufLen << 3; |
| 109 | |
Lev Walkin | 69c73dc | 2012-02-21 02:15:08 -0800 | [diff] [blame] | 110 | ASN_DEBUG_INDENT_ADD(+4); |
Bi-Ruei, Chiu | 1f87ac0 | 2017-08-20 01:25:45 +0800 | [diff] [blame] | 111 | rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd); |
Lev Walkin | 69c73dc | 2012-02-21 02:15:08 -0800 | [diff] [blame] | 112 | ASN_DEBUG_INDENT_ADD(-4); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 113 | |
Lev Walkin | 49f510f | 2007-06-29 17:33:04 +0000 | [diff] [blame] | 114 | if(rv.code == RC_OK) { |
| 115 | /* Check padding validity */ |
| 116 | padding = spd.nbits - spd.nboff; |
Lev Walkin | 190419b | 2010-10-25 19:19:17 -0700 | [diff] [blame] | 117 | if ((padding < 8 || |
| 118 | /* X.691#10.1.3 */ |
| 119 | (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) && |
Lev Walkin | a6dd57a | 2010-10-24 22:03:14 -0700 | [diff] [blame] | 120 | per_get_few_bits(&spd, padding) == 0) { |
Lev Walkin | 49f510f | 2007-06-29 17:33:04 +0000 | [diff] [blame] | 121 | /* Everything is cool */ |
| 122 | FREEMEM(buf); |
| 123 | return rv; |
| 124 | } |
| 125 | FREEMEM(buf); |
| 126 | if(padding >= 8) { |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 127 | ASN_DEBUG("Too large padding %d in open type", (int)padding); |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 128 | ASN__DECODE_FAILED; |
Lev Walkin | 49f510f | 2007-06-29 17:33:04 +0000 | [diff] [blame] | 129 | } else { |
| 130 | ASN_DEBUG("Non-zero padding"); |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 131 | ASN__DECODE_FAILED; |
Lev Walkin | 49f510f | 2007-06-29 17:33:04 +0000 | [diff] [blame] | 132 | } |
| 133 | } else { |
| 134 | FREEMEM(buf); |
Lev Walkin | 80515f0 | 2007-06-29 23:23:05 +0000 | [diff] [blame] | 135 | /* rv.code could be RC_WMORE, nonsense in this context */ |
| 136 | rv.code = RC_FAIL; /* Noone would give us more */ |
Lev Walkin | 55fdd99 | 2007-06-29 11:25:49 +0000 | [diff] [blame] | 137 | } |
| 138 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 139 | return rv; |
| 140 | } |
| 141 | |
Lev Walkin | 3f99563 | 2017-09-26 18:27:32 -0700 | [diff] [blame] | 142 | static asn_dec_rval_t CC_NOTUSED |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 143 | uper_open_type_get_complex(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 144 | 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 Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 149 | ASN__STACK_OVERFLOW_CHECK(ctx); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 150 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 151 | ASN_DEBUG("Getting open type %s from %s", td->name, |
Lev Walkin | 6cd0d56 | 2017-08-25 11:57:01 -0700 | [diff] [blame] | 152 | asn_bit_data_string(pd)); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 153 | 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 Walkin | 69c73dc | 2012-02-21 02:15:08 -0800 | [diff] [blame] | 162 | ASN_DEBUG_INDENT_ADD(+4); |
Bi-Ruei, Chiu | 1f87ac0 | 2017-08-20 01:25:45 +0800 | [diff] [blame] | 163 | rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd); |
Lev Walkin | 69c73dc | 2012-02-21 02:15:08 -0800 | [diff] [blame] | 164 | ASN_DEBUG_INDENT_ADD(-4); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 165 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 166 | #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 Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 179 | ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name, |
Lev Walkin | 6cd0d56 | 2017-08-25 11:57:01 -0700 | [diff] [blame] | 180 | asn_bit_data_string(pd), |
| 181 | asn_bit_data_string(&arg.oldpd), |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 182 | (int)arg.unclaimed, (int)arg.repeat); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 183 | |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 184 | 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 Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 189 | (int)padding); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 190 | rv.code = RC_FAIL; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 191 | UPDRESTOREPD; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 192 | return rv; |
| 193 | } |
| 194 | padding = 8 - padding; |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 195 | ASN_DEBUG("Getting padding of %d bits", (int)padding); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 196 | pvalue = per_get_few_bits(pd, padding); |
| 197 | switch(pvalue) { |
| 198 | case -1: |
| 199 | ASN_DEBUG("Padding skip failed"); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 200 | UPDRESTOREPD; |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 201 | ASN__DECODE_STARVED; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 202 | case 0: break; |
| 203 | default: |
| 204 | ASN_DEBUG("Non-blank padding (%d bits 0x%02x)", |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 205 | (int)padding, (int)pvalue); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 206 | UPDRESTOREPD; |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 207 | ASN__DECODE_FAILED; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 208 | } |
| 209 | } |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 210 | if(pd->nboff != pd->nbits) { |
| 211 | ASN_DEBUG("Open type %s overhead pd%s old%s", td->name, |
Lev Walkin | 6cd0d56 | 2017-08-25 11:57:01 -0700 | [diff] [blame] | 212 | asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd)); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 213 | if(1) { |
| 214 | UPDRESTOREPD; |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 215 | ASN__DECODE_FAILED; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 216 | } else { |
| 217 | arg.unclaimed += pd->nbits - pd->nboff; |
| 218 | } |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 219 | } |
| 220 | |
| 221 | /* Adjust pd back so it points to original data */ |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 222 | UPDRESTOREPD; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 223 | |
| 224 | /* Skip data not consumed by the decoder */ |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 225 | if(arg.unclaimed) { |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 226 | ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 227 | switch(per_skip_bits(pd, arg.unclaimed)) { |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 228 | case -1: |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 229 | ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed); |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 230 | ASN__DECODE_STARVED; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 231 | case 0: |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 232 | ASN_DEBUG("Got claim of %d", (int)arg.unclaimed); |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 233 | break; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 234 | default: |
| 235 | /* Padding must be blank */ |
| 236 | ASN_DEBUG("Non-blank unconsumed padding"); |
Lev Walkin | 7c1dc05 | 2016-03-14 03:08:15 -0700 | [diff] [blame] | 237 | ASN__DECODE_FAILED; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 238 | } |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 239 | arg.unclaimed = 0; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 240 | } |
| 241 | |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 242 | 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 Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 251 | |
| 252 | asn_dec_rval_t |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 253 | uper_open_type_get(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, |
Lev Walkin | 494fb70 | 2017-08-07 20:07:00 -0700 | [diff] [blame] | 254 | 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 Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 257 | } |
| 258 | |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 259 | int |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 260 | uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) { |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 261 | asn_TYPE_descriptor_t s_td; |
Lev Walkin | 75b6fe4 | 2017-08-27 01:03:22 -0700 | [diff] [blame] | 262 | asn_TYPE_operation_t s_op; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 263 | asn_dec_rval_t rv; |
| 264 | |
| 265 | s_td.name = "<unknown extension>"; |
Lev Walkin | 75b6fe4 | 2017-08-27 01:03:22 -0700 | [diff] [blame] | 266 | s_td.op = &s_op; |
| 267 | s_op.uper_decoder = uper_sot_suck; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 268 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 269 | rv = uper_open_type_get(ctx, &s_td, 0, 0, pd); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 270 | if(rv.code != RC_OK) |
| 271 | return -1; |
| 272 | else |
| 273 | return 0; |
| 274 | } |
| 275 | |
| 276 | /* |
| 277 | * Internal functions. |
| 278 | */ |
| 279 | |
| 280 | static asn_dec_rval_t |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 281 | uper_sot_suck(const asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, |
Lev Walkin | 494fb70 | 2017-08-07 20:07:00 -0700 | [diff] [blame] | 282 | const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 283 | asn_dec_rval_t rv; |
| 284 | |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 285 | (void)ctx; |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 286 | (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 | |
| 298 | static int |
| 299 | uper_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 Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 306 | ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld", |
| 307 | (long)pd->moved, (long)oldpd->moved); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 308 | |
| 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 Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 327 | ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)", |
| 328 | (long)pd->moved); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 329 | 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 Walkin | 9d1b45f | 2017-10-01 17:04:48 -0700 | [diff] [blame] | 337 | next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat); |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 338 | ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld", |
| 339 | (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 340 | 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 Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 350 | 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 Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 354 | } else { |
| 355 | pd->nbits = oldpd->nbits; |
| 356 | arg->unclaimed = next_chunk_bits - avail; |
Lev Walkin | fe1ffaf | 2010-10-25 21:07:59 -0700 | [diff] [blame] | 357 | ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld", |
| 358 | (long)avail, (long)next_chunk_bits, |
| 359 | (long)arg->unclaimed); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 360 | } |
| 361 | pd->buffer = oldpd->buffer; |
| 362 | pd->nboff = oldpd->nboff; |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 363 | ASN_DEBUG("Refilled pd%s old%s", |
Lev Walkin | 6cd0d56 | 2017-08-25 11:57:01 -0700 | [diff] [blame] | 364 | asn_bit_data_string(pd), asn_bit_data_string(oldpd)); |
Lev Walkin | 9218bc1 | 2007-06-27 04:09:37 +0000 | [diff] [blame] | 365 | return 0; |
| 366 | } |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 367 | |
| 368 | static int |
| 369 | per_skip_bits(asn_per_data_t *pd, int skip_nbits) { |
| 370 | int hasNonZeroBits = 0; |
| 371 | while(skip_nbits > 0) { |
| 372 | int skip; |
Lev Walkin | da16198 | 2013-03-20 03:35:21 -0700 | [diff] [blame] | 373 | |
| 374 | /* per_get_few_bits() is more efficient when nbits <= 24 */ |
| 375 | if(skip_nbits < 24) |
Lev Walkin | 375f0e9 | 2007-06-29 02:28:50 +0000 | [diff] [blame] | 376 | 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 | } |