SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / constr_SEQUENCE_ber.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <constr_SEQUENCE.h>
8 #include <OPEN_TYPE.h>
9
10 /*
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.
14  */
15 #define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
16
17 /*
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
21  * reading more data.
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.
27  */
28 #define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size)
29
30 /*
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.
33  */
34 #undef ADVANCE
35 #define ADVANCE(num_bytes)                \
36     do {                                  \
37         size_t num = num_bytes;           \
38         ptr = ((const char *)ptr) + num;  \
39         size -= num;                      \
40         if(ctx->left >= 0)                \
41             ctx->left -= num;             \
42         consumed_myself += num;           \
43     } while(0)
44
45 /*
46  * Switch to the next phase of parsing.
47  */
48 #undef NEXT_PHASE
49 #define NEXT_PHASE(ctx)  \
50     do {                 \
51         ctx->phase++;    \
52         ctx->step = 0;   \
53     } while(0)
54 #undef PHASE_OUT
55 #define PHASE_OUT(ctx)    \
56     do {                  \
57         ctx->phase = 10;  \
58     } while(0)
59
60 /*
61  * Return a standardized complex structure.
62  */
63 #undef RETURN
64 #define RETURN(_code)                     \
65     do {                                  \
66         rval.code = _code;                \
67         rval.consumed = consumed_myself;  \
68         return rval;                      \
69     } while(0)
70
71 /*
72  * Check whether we are inside the extensions group.
73  */
74 #define IN_EXTENSION_GROUP(specs, memb_idx)                \
75     ((specs)->first_extension >= 0                         \
76      && (unsigned)(specs)->first_extension <= (memb_idx))
77
78 /*
79  * Tags are canonically sorted in the tag2element map.
80  */
81 static int
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;
85
86     int a_class = BER_TAG_CLASS(a->el_tag);
87     int b_class = BER_TAG_CLASS(b->el_tag);
88
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);
92
93         if(a_value == b_value) {
94             if(a->el_no > b->el_no)
95                 return 1;
96             /*
97              * Important: we do not check
98              * for a->el_no <= b->el_no!
99              */
100             return 0;
101         } else if(a_value < b_value)
102             return -1;
103         else
104             return 1;
105     } else if(a_class < b_class) {
106         return -1;
107     } else {
108         return 1;
109     }
110 }
111
112 /*
113  * The decoder of the SEQUENCE type.
114  */
115 asn_dec_rval_t
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) {
119     /*
120      * Bring closer parts of structure description.
121      */
122     const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;
123     const asn_TYPE_member_t *elements = td->elements;
124
125     /*
126      * Parts of the structure being constructed.
127      */
128     void *st = *struct_ptr;  /* Target structure. */
129     asn_struct_ctx_t *ctx;   /* Decoder context */
130
131     ber_tlv_tag_t tlv_tag;  /* T from TLV */
132     asn_dec_rval_t rval;    /* Return code from subparsers */
133
134     ssize_t consumed_myself = 0;  /* Consumed bytes from ptr */
135     size_t edx;  /* SEQUENCE element's index */
136
137     ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
138
139     /*
140      * Create the target structure if it is not present already.
141      */
142     if(st == 0) {
143         st = *struct_ptr = CALLOC(1, specs->struct_size);
144         if(st == 0) {
145             RETURN(RC_FAIL);
146         }
147     }
148
149     /*
150      * Restore parsing context.
151      */
152     ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
153
154     /*
155      * Start to parse where left previously
156      */
157     switch(ctx->phase) {
158     case 0:
159         /*
160          * PHASE 0.
161          * Check that the set of tags associated with given structure
162          * perfectly fits our expectations.
163          */
164
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);
170             return rval;
171         }
172
173         if(ctx->left >= 0)
174             ctx->left += rval.consumed;  /* ?Subtracted below! */
175         ADVANCE(rval.consumed);
176
177         NEXT_PHASE(ctx);
178
179         ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
180                   (long)ctx->left, (long)size);
181
182         /* Fall through */
183     case 1:
184         /*
185          * PHASE 1.
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
191          * that member:
192          *     step = (<member_number> * 2 + <microphase>).
193          */
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 */
200             size_t n;
201             int use_bsearch;
202
203             if(ctx->step & 1)
204                 goto microphase2;
205
206             /*
207              * MICROPHASE 1: Synchronize decoding.
208              */
209             ASN_DEBUG("In %s SEQUENCE left %d, edx=%" ASN_PRI_SIZE " flags=%d"
210                       " opt=%d ec=%d",
211                       td->name, (int)ctx->left, edx,
212                       elements[edx].flags, elements[edx].optional,
213                       td->elements_count);
214
215             if(ctx->left == 0 /* No more stuff is expected */
216                && (
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);
222                 /*
223                  * Found the legitimate end of the structure.
224                  */
225                 PHASE_OUT(ctx);
226                 RETURN(RC_OK);
227             }
228
229             /*
230              * Fetch the T from TLV.
231              */
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);
237             switch(tag_len) {
238             case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
239                 /* Fall through */
240             case -1: RETURN(RC_FAIL);
241             }
242
243             if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
244                 if(LEFT < 2) {
245                     if(SIZE_VIOLATION) {
246                         RETURN(RC_FAIL);
247                     } else {
248                         RETURN(RC_WMORE);
249                     }
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)) {
255                         /*
256                          * Yeah, baby! Found the terminator
257                          * of the indefinite length structure.
258                          */
259                         /*
260                          * Proceed to the canonical
261                          * finalization function.
262                          * No advancing is necessary.
263                          */
264                         goto phase3;
265                     }
266                 }
267             }
268
269             /*
270              * Find the next available type with this tag.
271              */
272             use_bsearch = 0;
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;
279                 use_bsearch = 1;
280                 /* ... and resort to bsearch() */
281             }
282             for(n = edx; n < opt_edx_end; n++) {
283                 if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
284                     /*
285                      * Found element corresponding to the tag
286                      * being looked at.
287                      * Reposition over the right element.
288                      */
289                     edx = n;
290                     ctx->step = 1 + 2 * edx;  /* Remember! */
291                     goto microphase2;
292                 } else if(elements[n].flags & ATF_ANY_TYPE) {
293                     /*
294                      * This is the ANY type, which may bear
295                      * any flag whatsoever.
296                      */
297                     edx = n;
298                     ctx->step = 1 + 2 * edx;  /* Remember! */
299                     goto microphase2;
300                 } else if(elements[n].tag == (ber_tlv_tag_t)-1) {
301                     use_bsearch = 1;
302                     break;
303                 }
304             }
305             if(use_bsearch) {
306                 /*
307                  * Resort to a binary search over
308                  * sorted array of tags.
309                  */
310                 const asn_TYPE_tag2member_t *t2m;
311                 asn_TYPE_tag2member_t key = {0, 0, 0, 0};
312                 key.el_tag = tlv_tag;
313                 key.el_no = edx;
314                 t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
315                        specs->tag2el, specs->tag2el_count,
316                        sizeof(specs->tag2el[0]), _t2e_cmp);
317                 if(t2m) {
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;
321                     /*
322                      * Rewind to the first element with that tag,
323                      * `cause bsearch() does not guarantee order.
324                      */
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;
330                         best = t2m;
331                     }
332                     if(best) {
333                         edx = best->el_no;
334                         ctx->step = 1 + 2 * edx;
335                         goto microphase2;
336                     }
337                 }
338                 n = opt_edx_end;
339             }
340             if(n == opt_edx_end) {
341                 /*
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.
346                  */
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),
353                               elements[edx].name,
354                               elements[edx].optional ?" or alternatives":"");
355                     RETURN(RC_FAIL);
356                 } else {
357                     /* Skip this tag */
358                     ssize_t skip;
359                     edx += elements[edx].optional;
360
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,
366                                            LEFT - tag_len);
367                     ASN_DEBUG("Skip length %d in %s",
368                               (int)skip, td->name);
369                     switch(skip) {
370                     case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
371                         /* Fall through */
372                     case -1: RETURN(RC_FAIL);
373                     }
374
375                     ADVANCE(skip + tag_len);
376                     ctx->step -= 2;
377                     edx--;
378                     continue;  /* Try again with the next tag */
379                 }
380             }
381
382             /*
383              * MICROPHASE 2: Invoke the member-specific decoder.
384              */
385             ctx->step |= 1;  /* Confirm entering next microphase */
386         microphase2:
387             ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
388
389             /*
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).
393              */
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);
397             } else {
398                 /*
399                  * A pointer to a pointer
400                  * holding the start of the structure
401                  */
402                 memb_ptr = (char *)st + elements[edx].memb_offset;
403                 memb_ptr2 = &memb_ptr;
404             }
405             /*
406              * Invoke the member fetch routine according to member's type
407              */
408             if(elements[edx].flags & ATF_OPEN_TYPE) {
409                 rval = OPEN_TYPE_ber_get(opt_codec_ctx, td, st, &elements[edx], ptr, LEFT);
410             } else {
411                 rval = elements[edx].type->op->ber_decoder(opt_codec_ctx,
412                                                            elements[edx].type,
413                                                            memb_ptr2, ptr, LEFT,
414                                                            elements[edx].tag_mode);
415             }
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);
420             switch(rval.code) {
421             case RC_OK:
422                 break;
423             case RC_WMORE: /* More data expected */
424                 if(!SIZE_VIOLATION) {
425                     ADVANCE(rval.consumed);
426                     RETURN(RC_WMORE);
427                 }
428                 ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
429                           (long)ctx->left, (long)size);
430                 /* Fall through */
431             case RC_FAIL: /* Fatal error */
432                 RETURN(RC_FAIL);
433         } /* switch(rval) */
434
435         ADVANCE(rval.consumed);
436     }  /* for(all structure members) */
437
438     phase3:
439         ctx->phase = 3;
440         /* Fall through */
441     case 3:  /* 00 and other tags expected */
442     case 4:  /* only 00's expected */
443
444         ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
445                   td->name, (long)ctx->left, (long)size);
446
447         /*
448          * Skip everything until the end of the SEQUENCE.
449          */
450         while(ctx->left) {
451             ssize_t tl, ll;
452
453             tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
454             switch(tl) {
455             case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
456                 /* Fall through */
457             case -1: RETURN(RC_FAIL);
458             }
459
460             /*
461              * If expected <0><0>...
462              */
463             if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
464                 if(LEFT < 2) {
465                     if(SIZE_VIOLATION)
466                         RETURN(RC_FAIL);
467                     else
468                         RETURN(RC_WMORE);
469                 } else if(((const uint8_t *)ptr)[1] == 0) {
470                     /*
471                      * Correctly finished with <0><0>.
472                      */
473                     ADVANCE(2);
474                     ctx->left++;
475                     ctx->phase = 4;
476                     continue;
477                 }
478             }
479
480             if(!IN_EXTENSION_GROUP(specs, td->elements_count)
481             || ctx->phase == 4) {
482                 ASN_DEBUG("Unexpected continuation "
483                           "of a non-extensible type "
484                           "%s (SEQUENCE): %s",
485                           td->name,
486                           ber_tlv_tag_string(tlv_tag));
487                 RETURN(RC_FAIL);
488             }
489
490             ll = ber_skip_length(opt_codec_ctx,
491                                  BER_TLV_CONSTRUCTED(ptr),
492                                  (const char *)ptr + tl, LEFT - tl);
493             switch(ll) {
494             case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
495                 /* Fall through */
496             case -1: RETURN(RC_FAIL);
497             }
498
499             ADVANCE(tl + ll);
500         }
501
502         PHASE_OUT(ctx);
503     }
504
505     RETURN(RC_OK);
506 }
507
508
509 /*
510  * The DER encoder of the SEQUENCE type.
511  */
512 asn_enc_rval_t
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};
518     ssize_t ret;
519     size_t edx;
520
521     ASN_DEBUG("%s %s as SEQUENCE",
522               cb?"Encoding":"Estimating", td->name);
523
524     /*
525      * Gather the length of the underlying members sequence.
526      */
527     for(edx = 0; edx < td->elements_count; edx++) {
528         asn_TYPE_member_t *elm = &td->elements[edx];
529
530         const void *memb_ptr;          /* Pointer to the member */
531         const void *const *memb_ptr2;  /* Pointer to that pointer */
532
533         if(elm->flags & ATF_POINTER) {
534             memb_ptr2 =
535                 (const void *const *)((const char *)sptr + elm->memb_offset);
536             if(!*memb_ptr2) {
537                 ASN_DEBUG("Element %s %" ASN_PRI_SIZE " not present",
538                           elm->name, edx);
539                 if(elm->optional)
540                     continue;
541                 /* Mandatory element is missing */
542                 ASN__ENCODE_FAILED;
543             }
544         } else {
545             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
546             memb_ptr2 = &memb_ptr;
547         }
548
549         /* Eliminate default values */
550         if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)
551             continue;
552
553         erval = elm->type->op->der_encoder(elm->type, *memb_ptr2,
554                                            elm->tag_mode, elm->tag,
555                                            0, 0);
556         if(erval.encoded == -1)
557             return erval;
558         computed_size += erval.encoded;
559         ASN_DEBUG("Member %" ASN_PRI_SIZE " %s estimated %ld bytes",
560                   edx, elm->name, (long)erval.encoded);
561     }
562
563     /*
564      * Encode the TLV for the sequence itself.
565      */
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);
568     if(ret == -1)
569         ASN__ENCODE_FAILED;
570     erval.encoded = computed_size + ret;
571
572     if(!cb) ASN__ENCODED_OK(erval);
573
574     /*
575      * Encode all members.
576      */
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 */
582
583         if(elm->flags & ATF_POINTER) {
584             memb_ptr2 =
585                 (const void *const *)((const char *)sptr + elm->memb_offset);
586             if(!*memb_ptr2) continue;
587         } else {
588             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
589             memb_ptr2 = &memb_ptr;
590         }
591
592         /* Eliminate default values */
593         if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)
594             continue;
595
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)
599             return tmperval;
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);
603     }
604
605     if(computed_size != 0)
606         /*
607          * Encoded size is not equal to the computed size.
608          */
609         ASN__ENCODE_FAILED;
610
611     ASN__ENCODED_OK(erval);
612 }