2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <constr_SEQUENCE.h>
11 * Number of bytes left for this structure.
12 * (ctx->left) indicates the number of bytes _transferred_ for the structure.
13 * (size) contains the number of bytes in the buffer passed.
15 #define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
18 * If the subprocessor function returns with an indication that it wants
19 * more data, it may well be a fatal decoding problem, because the
20 * size is constrained by the <TLV>'s L, even if the buffer size allows
22 * For example, consider the buffer containing the following TLVs:
23 * <T:5><L:1><V> <T:6>...
24 * The TLV length clearly indicates that one byte is expected in V, but
25 * if the V processor returns with "want more data" even if the buffer
26 * contains way more data than the V processor have seen.
28 #define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size)
31 * This macro "eats" the part of the buffer which is definitely "consumed",
32 * i.e. was correctly converted into local representation or rightfully skipped.
35 #define ADVANCE(num_bytes) \
37 size_t num = num_bytes; \
38 ptr = ((const char *)ptr) + num; \
42 consumed_myself += num; \
46 * Switch to the next phase of parsing.
49 #define NEXT_PHASE(ctx) \
55 #define PHASE_OUT(ctx) \
61 * Return a standardized complex structure.
64 #define RETURN(_code) \
67 rval.consumed = consumed_myself; \
72 * Check whether we are inside the extensions group.
74 #define IN_EXTENSION_GROUP(specs, memb_idx) \
75 ((specs)->first_extension >= 0 \
76 && (unsigned)(specs)->first_extension <= (memb_idx))
79 * Tags are canonically sorted in the tag2element map.
82 _t2e_cmp(const void *ap, const void *bp) {
83 const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
84 const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
86 int a_class = BER_TAG_CLASS(a->el_tag);
87 int b_class = BER_TAG_CLASS(b->el_tag);
89 if(a_class == b_class) {
90 ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
91 ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
93 if(a_value == b_value) {
94 if(a->el_no > b->el_no)
97 * Important: we do not check
98 * for a->el_no <= b->el_no!
101 } else if(a_value < b_value)
105 } else if(a_class < b_class) {
113 * The decoder of the SEQUENCE type.
116 SEQUENCE_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
117 const asn_TYPE_descriptor_t *td, void **struct_ptr,
118 const void *ptr, size_t size, int tag_mode) {
120 * Bring closer parts of structure description.
122 const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;
123 const asn_TYPE_member_t *elements = td->elements;
126 * Parts of the structure being constructed.
128 void *st = *struct_ptr; /* Target structure. */
129 asn_struct_ctx_t *ctx; /* Decoder context */
131 ber_tlv_tag_t tlv_tag; /* T from TLV */
132 asn_dec_rval_t rval; /* Return code from subparsers */
134 ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
135 size_t edx; /* SEQUENCE element's index */
137 ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
140 * Create the target structure if it is not present already.
143 st = *struct_ptr = CALLOC(1, specs->struct_size);
150 * Restore parsing context.
152 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
155 * Start to parse where left previously
161 * Check that the set of tags associated with given structure
162 * perfectly fits our expectations.
165 rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
166 tag_mode, 1, &ctx->left, 0);
167 if(rval.code != RC_OK) {
168 ASN_DEBUG("%s tagging check failed: %d",
169 td->name, rval.code);
174 ctx->left += rval.consumed; /* ?Subtracted below! */
175 ADVANCE(rval.consumed);
179 ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
180 (long)ctx->left, (long)size);
186 * From the place where we've left it previously,
187 * try to decode the next member from the list of
188 * this structure's elements.
189 * (ctx->step) stores the member being processed
190 * between invocations and the microphase {0,1} of parsing
192 * step = (<member_number> * 2 + <microphase>).
194 for(edx = ((size_t)ctx->step >> 1); edx < td->elements_count;
195 edx++, ctx->step = (ctx->step & ~1) + 2) {
196 void *memb_ptr; /* Pointer to the member */
197 void **memb_ptr2; /* Pointer to that pointer */
198 ssize_t tag_len; /* Length of TLV's T */
199 size_t opt_edx_end; /* Next non-optional element */
207 * MICROPHASE 1: Synchronize decoding.
209 ASN_DEBUG("In %s SEQUENCE left %d, edx=%" ASN_PRI_SIZE " flags=%d"
211 td->name, (int)ctx->left, edx,
212 elements[edx].flags, elements[edx].optional,
215 if(ctx->left == 0 /* No more stuff is expected */
217 /* Explicit OPTIONAL specification reaches the end */
218 (edx + elements[edx].optional == td->elements_count) ||
219 /* All extensions are optional */
220 IN_EXTENSION_GROUP(specs, edx))) {
221 ASN_DEBUG("End of SEQUENCE %s", td->name);
223 * Found the legitimate end of the structure.
230 * Fetch the T from TLV.
232 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
233 ASN_DEBUG("Current tag in %s SEQUENCE for element %" ASN_PRI_SIZE " "
234 "(%s) is %s encoded in %d bytes, of frame %ld",
235 td->name, edx, elements[edx].name,
236 ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
238 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
240 case -1: RETURN(RC_FAIL);
243 if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
250 } else if(((const uint8_t *)ptr)[1] == 0) {
251 ASN_DEBUG("edx = %" ASN_PRI_SIZE ", opt = %d, ec=%d", edx,
252 elements[edx].optional, td->elements_count);
253 if((edx + elements[edx].optional == td->elements_count)
254 || IN_EXTENSION_GROUP(specs, edx)) {
256 * Yeah, baby! Found the terminator
257 * of the indefinite length structure.
260 * Proceed to the canonical
261 * finalization function.
262 * No advancing is necessary.
270 * Find the next available type with this tag.
273 opt_edx_end = edx + elements[edx].optional + 1;
274 if(opt_edx_end > td->elements_count)
275 opt_edx_end = td->elements_count; /* Cap */
276 else if(opt_edx_end - edx > 8) {
277 /* Limit the scope of linear search... */
278 opt_edx_end = edx + 8;
280 /* ... and resort to bsearch() */
282 for(n = edx; n < opt_edx_end; n++) {
283 if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
285 * Found element corresponding to the tag
287 * Reposition over the right element.
290 ctx->step = 1 + 2 * edx; /* Remember! */
292 } else if(elements[n].flags & ATF_ANY_TYPE) {
294 * This is the ANY type, which may bear
295 * any flag whatsoever.
298 ctx->step = 1 + 2 * edx; /* Remember! */
300 } else if(elements[n].tag == (ber_tlv_tag_t)-1) {
307 * Resort to a binary search over
308 * sorted array of tags.
310 const asn_TYPE_tag2member_t *t2m;
311 asn_TYPE_tag2member_t key = {0, 0, 0, 0};
312 key.el_tag = tlv_tag;
314 t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
315 specs->tag2el, specs->tag2el_count,
316 sizeof(specs->tag2el[0]), _t2e_cmp);
318 const asn_TYPE_tag2member_t *best = 0;
319 const asn_TYPE_tag2member_t *t2m_f, *t2m_l;
320 size_t edx_max = edx + elements[edx].optional;
322 * Rewind to the first element with that tag,
323 * `cause bsearch() does not guarantee order.
325 t2m_f = t2m + t2m->toff_first;
326 t2m_l = t2m + t2m->toff_last;
327 for(t2m = t2m_f; t2m <= t2m_l; t2m++) {
328 if(t2m->el_no > edx_max) break;
329 if(t2m->el_no < edx) continue;
334 ctx->step = 1 + 2 * edx;
340 if(n == opt_edx_end) {
342 * If tag is unknown, it may be either
343 * an unknown (thus, incorrect) tag,
344 * or an extension (...),
345 * or an end of the indefinite-length structure.
347 if(!IN_EXTENSION_GROUP(specs,
348 edx + elements[edx].optional)) {
349 ASN_DEBUG("Unexpected tag %s (at %" ASN_PRI_SIZE ")",
350 ber_tlv_tag_string(tlv_tag), edx);
351 ASN_DEBUG("Expected tag %s (%s)%s",
352 ber_tlv_tag_string(elements[edx].tag),
354 elements[edx].optional ?" or alternatives":"");
359 edx += elements[edx].optional;
361 ASN_DEBUG("Skipping unexpected %s (at %" ASN_PRI_SIZE ")",
362 ber_tlv_tag_string(tlv_tag), edx);
363 skip = ber_skip_length(opt_codec_ctx,
364 BER_TLV_CONSTRUCTED(ptr),
365 (const char *)ptr + tag_len,
367 ASN_DEBUG("Skip length %d in %s",
368 (int)skip, td->name);
370 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
372 case -1: RETURN(RC_FAIL);
375 ADVANCE(skip + tag_len);
378 continue; /* Try again with the next tag */
383 * MICROPHASE 2: Invoke the member-specific decoder.
385 ctx->step |= 1; /* Confirm entering next microphase */
387 ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
390 * Compute the position of the member inside a structure,
391 * and also a type of containment (it may be contained
392 * as pointer or using inline inclusion).
394 if(elements[edx].flags & ATF_POINTER) {
395 /* Member is a pointer to another structure */
396 memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
399 * A pointer to a pointer
400 * holding the start of the structure
402 memb_ptr = (char *)st + elements[edx].memb_offset;
403 memb_ptr2 = &memb_ptr;
406 * Invoke the member fetch routine according to member's type
408 if(elements[edx].flags & ATF_OPEN_TYPE) {
409 rval = OPEN_TYPE_ber_get(opt_codec_ctx, td, st, &elements[edx], ptr, LEFT);
411 rval = elements[edx].type->op->ber_decoder(opt_codec_ctx,
413 memb_ptr2, ptr, LEFT,
414 elements[edx].tag_mode);
416 ASN_DEBUG("In %s SEQUENCE decoded %" ASN_PRI_SIZE " %s of %d "
417 "in %d bytes rval.code %d, size=%d",
418 td->name, edx, elements[edx].type->name,
419 (int)LEFT, (int)rval.consumed, rval.code, (int)size);
423 case RC_WMORE: /* More data expected */
424 if(!SIZE_VIOLATION) {
425 ADVANCE(rval.consumed);
428 ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
429 (long)ctx->left, (long)size);
431 case RC_FAIL: /* Fatal error */
435 ADVANCE(rval.consumed);
436 } /* for(all structure members) */
441 case 3: /* 00 and other tags expected */
442 case 4: /* only 00's expected */
444 ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
445 td->name, (long)ctx->left, (long)size);
448 * Skip everything until the end of the SEQUENCE.
453 tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
455 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
457 case -1: RETURN(RC_FAIL);
461 * If expected <0><0>...
463 if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
469 } else if(((const uint8_t *)ptr)[1] == 0) {
471 * Correctly finished with <0><0>.
480 if(!IN_EXTENSION_GROUP(specs, td->elements_count)
481 || ctx->phase == 4) {
482 ASN_DEBUG("Unexpected continuation "
483 "of a non-extensible type "
486 ber_tlv_tag_string(tlv_tag));
490 ll = ber_skip_length(opt_codec_ctx,
491 BER_TLV_CONSTRUCTED(ptr),
492 (const char *)ptr + tl, LEFT - tl);
494 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
496 case -1: RETURN(RC_FAIL);
510 * The DER encoder of the SEQUENCE type.
513 SEQUENCE_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
514 int tag_mode, ber_tlv_tag_t tag,
515 asn_app_consume_bytes_f *cb, void *app_key) {
516 size_t computed_size = 0;
517 asn_enc_rval_t erval = {0,0,0};
521 ASN_DEBUG("%s %s as SEQUENCE",
522 cb?"Encoding":"Estimating", td->name);
525 * Gather the length of the underlying members sequence.
527 for(edx = 0; edx < td->elements_count; edx++) {
528 asn_TYPE_member_t *elm = &td->elements[edx];
530 const void *memb_ptr; /* Pointer to the member */
531 const void *const *memb_ptr2; /* Pointer to that pointer */
533 if(elm->flags & ATF_POINTER) {
535 (const void *const *)((const char *)sptr + elm->memb_offset);
537 ASN_DEBUG("Element %s %" ASN_PRI_SIZE " not present",
541 /* Mandatory element is missing */
545 memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
546 memb_ptr2 = &memb_ptr;
549 /* Eliminate default values */
550 if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)
553 erval = elm->type->op->der_encoder(elm->type, *memb_ptr2,
554 elm->tag_mode, elm->tag,
556 if(erval.encoded == -1)
558 computed_size += erval.encoded;
559 ASN_DEBUG("Member %" ASN_PRI_SIZE " %s estimated %ld bytes",
560 edx, elm->name, (long)erval.encoded);
564 * Encode the TLV for the sequence itself.
566 ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
567 ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
570 erval.encoded = computed_size + ret;
572 if(!cb) ASN__ENCODED_OK(erval);
575 * Encode all members.
577 for(edx = 0; edx < td->elements_count; edx++) {
578 asn_TYPE_member_t *elm = &td->elements[edx];
579 asn_enc_rval_t tmperval = {0,0,0};
580 const void *memb_ptr; /* Pointer to the member */
581 const void *const *memb_ptr2; /* Pointer to that pointer */
583 if(elm->flags & ATF_POINTER) {
585 (const void *const *)((const char *)sptr + elm->memb_offset);
586 if(!*memb_ptr2) continue;
588 memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
589 memb_ptr2 = &memb_ptr;
592 /* Eliminate default values */
593 if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)
596 tmperval = elm->type->op->der_encoder(elm->type, *memb_ptr2,
597 elm->tag_mode, elm->tag, cb, app_key);
598 if(tmperval.encoded == -1)
600 computed_size -= tmperval.encoded;
601 ASN_DEBUG("Member %" ASN_PRI_SIZE " %s of SEQUENCE %s encoded in %ld bytes",
602 edx, elm->name, td->name, (long)tmperval.encoded);
605 if(computed_size != 0)
607 * Encoded size is not equal to the computed size.
611 ASN__ENCODED_OK(erval);