]> git.stg.codes - stg.git/blob - libs/smux/constr_SET_OF.c
Fix build on Darwin.
[stg.git] / libs / smux / constr_SET_OF.c
1 /*
2  * Copyright (c) 2003-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_SET_OF.h>
8 #include <asn_SET_OF.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)      do {            \
36                 size_t num = num_bytes;         \
37                 ptr = ((const char *)ptr) + num;\
38                 size -= num;                    \
39                 if(ctx->left >= 0)              \
40                         ctx->left -= num;       \
41                 consumed_myself += num;         \
42         } while(0)
43
44 /*
45  * Switch to the next phase of parsing.
46  */
47 #undef  NEXT_PHASE
48 #undef  PHASE_OUT
49 #define NEXT_PHASE(ctx) do {                    \
50                 ctx->phase++;                   \
51                 ctx->step = 0;                  \
52         } while(0)
53 #define PHASE_OUT(ctx)  do { ctx->phase = 10; } while(0)
54
55 /*
56  * Return a standardized complex structure.
57  */
58 #undef  RETURN
59 #define RETURN(_code)   do {                    \
60                 rval.code = _code;              \
61                 rval.consumed = consumed_myself;\
62                 return rval;                    \
63         } while(0)
64
65 /*
66  * The decoder of the SET OF type.
67  */
68 asn_dec_rval_t
69 SET_OF_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
70                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
71                   const void *ptr, size_t size, int tag_mode) {
72     /*
73          * Bring closer parts of structure description.
74          */
75         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
76     const asn_TYPE_member_t *elm = td->elements; /* Single one */
77
78     /*
79          * Parts of the structure being constructed.
80          */
81         void *st = *struct_ptr; /* Target structure. */
82         asn_struct_ctx_t *ctx;  /* Decoder context */
83
84         ber_tlv_tag_t tlv_tag;  /* T from TLV */
85         asn_dec_rval_t rval;    /* Return code from subparsers */
86
87         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
88
89         ASN_DEBUG("Decoding %s as SET OF", td->name);
90         
91         /*
92          * Create the target structure if it is not present already.
93          */
94         if(st == 0) {
95                 st = *struct_ptr = CALLOC(1, specs->struct_size);
96                 if(st == 0) {
97                         RETURN(RC_FAIL);
98                 }
99         }
100
101         /*
102          * Restore parsing context.
103          */
104         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
105         
106         /*
107          * Start to parse where left previously
108          */
109         switch(ctx->phase) {
110         case 0:
111                 /*
112                  * PHASE 0.
113                  * Check that the set of tags associated with given structure
114                  * perfectly fits our expectations.
115                  */
116
117                 rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
118                         tag_mode, 1, &ctx->left, 0);
119                 if(rval.code != RC_OK) {
120                         ASN_DEBUG("%s tagging check failed: %d",
121                                 td->name, rval.code);
122                         return rval;
123                 }
124
125                 if(ctx->left >= 0)
126                         ctx->left += rval.consumed; /* ?Substracted below! */
127                 ADVANCE(rval.consumed);
128
129                 ASN_DEBUG("Structure consumes %ld bytes, "
130                         "buffer %ld", (long)ctx->left, (long)size);
131
132                 NEXT_PHASE(ctx);
133                 /* Fall through */
134         case 1:
135                 /*
136                  * PHASE 1.
137                  * From the place where we've left it previously,
138                  * try to decode the next item.
139                  */
140           for(;; ctx->step = 0) {
141                 ssize_t tag_len;        /* Length of TLV's T */
142
143                 if(ctx->step & 1)
144                         goto microphase2;
145
146                 /*
147                  * MICROPHASE 1: Synchronize decoding.
148                  */
149
150                 if(ctx->left == 0) {
151                         ASN_DEBUG("End of SET OF %s", td->name);
152                         /*
153                          * No more things to decode.
154                          * Exit out of here.
155                          */
156                         PHASE_OUT(ctx);
157                         RETURN(RC_OK);
158                 }
159
160                 /*
161                  * Fetch the T from TLV.
162                  */
163                 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
164                 switch(tag_len) {
165                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
166                         /* Fall through */
167                 case -1: RETURN(RC_FAIL);
168                 }
169
170                 if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
171                         if(LEFT < 2) {
172                                 if(SIZE_VIOLATION)
173                                         RETURN(RC_FAIL);
174                                 else
175                                         RETURN(RC_WMORE);
176                         } else if(((const uint8_t *)ptr)[1] == 0) {
177                                 /*
178                                  * Found the terminator of the
179                                  * indefinite length structure.
180                                  */
181                                 break;
182                         }
183                 }
184
185                 /* Outmost tag may be unknown and cannot be fetched/compared */
186                 if(elm->tag != (ber_tlv_tag_t)-1) {
187                     if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
188                         /*
189                          * The new list member of expected type has arrived.
190                          */
191                     } else {
192                         ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
193                                 ber_tlv_tag_string(tlv_tag), td->name);
194                         ASN_DEBUG("%s SET OF has tag %s",
195                                 td->name, ber_tlv_tag_string(elm->tag));
196                         RETURN(RC_FAIL);
197                     }
198                 }
199
200                 /*
201                  * MICROPHASE 2: Invoke the member-specific decoder.
202                  */
203                 ctx->step |= 1;         /* Confirm entering next microphase */
204         microphase2:
205                 
206                 /*
207                  * Invoke the member fetch routine according to member's type
208                  */
209                 rval = elm->type->op->ber_decoder(opt_codec_ctx,
210                                 elm->type, &ctx->ptr, ptr, LEFT, 0);
211                 ASN_DEBUG("In %s SET OF %s code %d consumed %d",
212                         td->name, elm->type->name,
213                         rval.code, (int)rval.consumed);
214                 switch(rval.code) {
215                 case RC_OK:
216                         {
217                                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
218                                 if(ASN_SET_ADD(list, ctx->ptr) != 0)
219                                         RETURN(RC_FAIL);
220                                 else
221                                         ctx->ptr = 0;
222                         }
223                         break;
224                 case RC_WMORE: /* More data expected */
225                         if(!SIZE_VIOLATION) {
226                                 ADVANCE(rval.consumed);
227                                 RETURN(RC_WMORE);
228                         }
229                         /* Fall through */
230                 case RC_FAIL: /* Fatal error */
231                         ASN_STRUCT_FREE(*elm->type, ctx->ptr);
232                         ctx->ptr = 0;
233                         RETURN(RC_FAIL);
234                 } /* switch(rval) */
235                 
236                 ADVANCE(rval.consumed);
237           }     /* for(all list members) */
238
239                 NEXT_PHASE(ctx);
240         case 2:
241                 /*
242                  * Read in all "end of content" TLVs.
243                  */
244                 while(ctx->left < 0) {
245                         if(LEFT < 2) {
246                                 if(LEFT > 0 && ((const char *)ptr)[0] != 0) {
247                                         /* Unexpected tag */
248                                         RETURN(RC_FAIL);
249                                 } else {
250                                         RETURN(RC_WMORE);
251                                 }
252                         }
253                         if(((const char *)ptr)[0] == 0
254                         && ((const char *)ptr)[1] == 0) {
255                                 ADVANCE(2);
256                                 ctx->left++;
257                         } else {
258                                 RETURN(RC_FAIL);
259                         }
260                 }
261
262                 PHASE_OUT(ctx);
263         }
264         
265         RETURN(RC_OK);
266 }
267
268 /*
269  * Internally visible buffer holding a single encoded element.
270  */
271 struct _el_buffer {
272         uint8_t *buf;
273         size_t length;
274         size_t allocated_size;
275     unsigned bits_unused;
276 };
277 /* Append bytes to the above structure */
278 static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
279     struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
280
281     if(el_buf->length + size > el_buf->allocated_size) {
282         size_t new_size = el_buf->allocated_size ? el_buf->allocated_size : 8;
283         void *p;
284
285         do {
286             new_size <<= 2;
287         } while(el_buf->length + size > new_size);
288
289         p = REALLOC(el_buf->buf, new_size);
290         if(p) {
291             el_buf->buf = p;
292             el_buf->allocated_size = new_size;
293         } else {
294             return -1;
295         }
296     }
297
298     memcpy(el_buf->buf + el_buf->length, buffer, size);
299
300     el_buf->length += size;
301     return 0;
302 }
303
304 static void assert_unused_bits(const struct _el_buffer* p) {
305     if(p->length) {
306         assert((p->buf[p->length-1] & ~(0xff << p->bits_unused)) == 0);
307     } else {
308         assert(p->bits_unused == 0);
309     }
310 }
311
312 static int _el_buf_cmp(const void *ap, const void *bp) {
313     const struct _el_buffer *a = (const struct _el_buffer *)ap;
314     const struct _el_buffer *b = (const struct _el_buffer *)bp;
315     size_t common_len;
316     int ret = 0;
317
318     if(a->length < b->length)
319         common_len = a->length;
320     else
321         common_len = b->length;
322
323     if (a->buf && b->buf) {
324         ret = memcmp(a->buf, b->buf, common_len);
325     }
326     if(ret == 0) {
327         if(a->length < b->length)
328             ret = -1;
329         else if(a->length > b->length)
330             ret = 1;
331         /* Ignore unused bits. */
332         assert_unused_bits(a);
333         assert_unused_bits(b);
334     }
335
336     return ret;
337 }
338
339 static void
340 SET_OF__encode_sorted_free(struct _el_buffer *el_buf, size_t count) {
341     size_t i;
342
343     for(i = 0; i < count; i++) {
344         FREEMEM(el_buf[i].buf);
345     }
346
347     FREEMEM(el_buf);
348 }
349
350 enum SET_OF__encode_method {
351     SOES_DER,   /* Distinguished Encoding Rules */
352     SOES_CUPER  /* Canonical Unaligned Packed Encoding Rules */
353 };
354
355 static struct _el_buffer *
356 SET_OF__encode_sorted(const asn_TYPE_member_t *elm,
357                       const asn_anonymous_set_ *list,
358                       enum SET_OF__encode_method method) {
359     struct _el_buffer *encoded_els;
360     int edx;
361
362     encoded_els =
363         (struct _el_buffer *)CALLOC(list->count, sizeof(encoded_els[0]));
364     if(encoded_els == NULL) {
365         return NULL;
366     }
367
368         /*
369          * Encode all members.
370          */
371     for(edx = 0; edx < list->count; edx++) {
372         const void *memb_ptr = list->array[edx];
373         struct _el_buffer *encoding_el = &encoded_els[edx];
374         asn_enc_rval_t erval;
375
376         if(!memb_ptr) break;
377
378         /*
379                  * Encode the member into the prepared space.
380                  */
381         switch(method) {
382         case SOES_DER:
383             erval = elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag,
384                                                _el_addbytes, encoding_el);
385             break;
386         case SOES_CUPER:
387             erval = uper_encode(elm->type,
388                                 elm->encoding_constraints.per_constraints,
389                                 memb_ptr, _el_addbytes, encoding_el);
390             if(erval.encoded != -1) {
391                 size_t extra_bits = erval.encoded % 8;
392                 assert(encoding_el->length == (size_t)(erval.encoded + 7) / 8);
393                 encoding_el->bits_unused = (8 - extra_bits) & 0x7;
394             }
395             break;
396         default:
397             assert(!"Unreachable");
398             break;
399         }
400         if(erval.encoded < 0) break;
401         }
402
403     if(edx == list->count) {
404         /*
405          * Sort the encoded elements according to their encoding.
406          */
407         qsort(encoded_els, list->count, sizeof(encoded_els[0]), _el_buf_cmp);
408
409         return encoded_els;
410     } else {
411         SET_OF__encode_sorted_free(encoded_els, edx);
412         return NULL;
413     }
414 }
415
416
417 /*
418  * The DER encoder of the SET OF type.
419  */
420 asn_enc_rval_t
421 SET_OF_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
422                   int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
423                   void *app_key) {
424     const asn_TYPE_member_t *elm = td->elements;
425     const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
426     size_t computed_size = 0;
427     ssize_t encoding_size = 0;
428     struct _el_buffer *encoded_els;
429     int edx;
430
431         ASN_DEBUG("Estimating size for SET OF %s", td->name);
432
433     /*
434      * Gather the length of the underlying members sequence.
435      */
436     for(edx = 0; edx < list->count; edx++) {
437         void *memb_ptr = list->array[edx];
438         asn_enc_rval_t erval;
439
440         if(!memb_ptr) ASN__ENCODE_FAILED;
441
442         erval =
443             elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag, 0, 0);
444         if(erval.encoded == -1) return erval;
445         computed_size += erval.encoded;
446         }
447
448
449     /*
450      * Encode the TLV for the sequence itself.
451      */
452     encoding_size =
453         der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
454     if(encoding_size < 0) {
455         ASN__ENCODE_FAILED;
456     }
457     computed_size += encoding_size;
458
459     if(!cb || list->count == 0) {
460         asn_enc_rval_t erval;
461         erval.encoded = computed_size;
462         ASN__ENCODED_OK(erval);
463     }
464
465     ASN_DEBUG("Encoding members of %s SET OF", td->name);
466
467     /*
468      * DER mandates dynamic sorting of the SET OF elements
469      * according to their encodings. Build an array of the
470      * encoded elements.
471      */
472     encoded_els = SET_OF__encode_sorted(elm, list, SOES_DER);
473
474     /*
475      * Report encoded elements to the application.
476      * Dispose of temporary sorted members table.
477      */
478     for(edx = 0; edx < list->count; edx++) {
479         struct _el_buffer *encoded_el = &encoded_els[edx];
480         /* Report encoded chunks to the application */
481         if(cb(encoded_el->buf, encoded_el->length, app_key) < 0) {
482             break;
483         } else {
484             encoding_size += encoded_el->length;
485         }
486     }
487
488     SET_OF__encode_sorted_free(encoded_els, list->count);
489
490     if(edx == list->count) {
491         asn_enc_rval_t erval;
492         assert(computed_size == (size_t)encoding_size);
493         erval.encoded = computed_size;
494         ASN__ENCODED_OK(erval);
495     } else {
496         ASN__ENCODE_FAILED;
497     }
498 }
499
500 #undef  XER_ADVANCE
501 #define XER_ADVANCE(num_bytes)  do {                    \
502                 size_t num = num_bytes;                 \
503                 buf_ptr = ((const char *)buf_ptr) + num;\
504                 size -= num;                            \
505                 consumed_myself += num;                 \
506         } while(0)
507
508 /*
509  * Decode the XER (XML) data.
510  */
511 asn_dec_rval_t
512 SET_OF_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
513                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
514                   const char *opt_mname, const void *buf_ptr, size_t size) {
515     /*
516          * Bring closer parts of structure description.
517          */
518         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
519         const asn_TYPE_member_t *element = td->elements;
520         const char *elm_tag;
521         const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
522
523         /*
524          * ... and parts of the structure being constructed.
525          */
526         void *st = *struct_ptr; /* Target structure. */
527         asn_struct_ctx_t *ctx;  /* Decoder context */
528
529         asn_dec_rval_t rval;            /* Return value from a decoder */
530         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
531
532         /*
533          * Create the target structure if it is not present already.
534          */
535         if(st == 0) {
536                 st = *struct_ptr = CALLOC(1, specs->struct_size);
537                 if(st == 0) RETURN(RC_FAIL);
538         }
539
540         /* Which tag is expected for the downstream */
541         if(specs->as_XMLValueList) {
542                 elm_tag = (specs->as_XMLValueList == 1) ? 0 : "";
543         } else {
544                 elm_tag = (*element->name)
545                                 ? element->name : element->type->xml_tag;
546         }
547
548         /*
549          * Restore parsing context.
550          */
551         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
552
553         /*
554          * Phases of XER/XML processing:
555          * Phase 0: Check that the opening tag matches our expectations.
556          * Phase 1: Processing body and reacting on closing tag.
557          * Phase 2: Processing inner type.
558          */
559         for(; ctx->phase <= 2;) {
560                 pxer_chunk_type_e ch_type;      /* XER chunk type */
561                 ssize_t ch_size;                /* Chunk size */
562                 xer_check_tag_e tcv;            /* Tag check value */
563
564                 /*
565                  * Go inside the inner member of a set.
566                  */
567                 if(ctx->phase == 2) {
568                         asn_dec_rval_t tmprval;
569
570                         /* Invoke the inner type decoder, m.b. multiple times */
571                         ASN_DEBUG("XER/SET OF element [%s]", elm_tag);
572                         tmprval = element->type->op->xer_decoder(opt_codec_ctx,
573                                         element->type, &ctx->ptr, elm_tag,
574                                         buf_ptr, size);
575                         if(tmprval.code == RC_OK) {
576                                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
577                                 if(ASN_SET_ADD(list, ctx->ptr) != 0)
578                                         RETURN(RC_FAIL);
579                                 ctx->ptr = 0;
580                                 XER_ADVANCE(tmprval.consumed);
581                         } else {
582                                 XER_ADVANCE(tmprval.consumed);
583                                 RETURN(tmprval.code);
584                         }
585                         ctx->phase = 1; /* Back to body processing */
586                         ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
587                         /* Fall through */
588                 }
589
590                 /*
591                  * Get the next part of the XML stream.
592                  */
593                 ch_size = xer_next_token(&ctx->context,
594                         buf_ptr, size, &ch_type);
595                 if(ch_size == -1) {
596             RETURN(RC_FAIL);
597         } else {
598                         switch(ch_type) {
599             case PXER_WMORE:
600                 RETURN(RC_WMORE);
601                         case PXER_COMMENT:      /* Got XML comment */
602                         case PXER_TEXT:         /* Ignore free-standing text */
603                                 XER_ADVANCE(ch_size);   /* Skip silently */
604                                 continue;
605                         case PXER_TAG:
606                                 break;  /* Check the rest down there */
607                         }
608                 }
609
610                 tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
611                 ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s",
612                         tcv, ctx->phase, xml_tag);
613                 switch(tcv) {
614                 case XCT_CLOSING:
615                         if(ctx->phase == 0) break;
616                         ctx->phase = 0;
617                         /* Fall through */
618                 case XCT_BOTH:
619                         if(ctx->phase == 0) {
620                                 /* No more things to decode */
621                                 XER_ADVANCE(ch_size);
622                                 ctx->phase = 3; /* Phase out */
623                                 RETURN(RC_OK);
624                         }
625                         /* Fall through */
626                 case XCT_OPENING:
627                         if(ctx->phase == 0) {
628                                 XER_ADVANCE(ch_size);
629                                 ctx->phase = 1; /* Processing body phase */
630                                 continue;
631                         }
632                         /* Fall through */
633                 case XCT_UNKNOWN_OP:
634                 case XCT_UNKNOWN_BO:
635
636                         ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase);
637                         if(ctx->phase == 1) {
638                                 /*
639                                  * Process a single possible member.
640                                  */
641                                 ctx->phase = 2;
642                                 continue;
643                         }
644                         /* Fall through */
645                 default:
646                         break;
647                 }
648
649                 ASN_DEBUG("Unexpected XML tag in SET OF");
650                 break;
651         }
652
653         ctx->phase = 3; /* "Phase out" on hard failure */
654         RETURN(RC_FAIL);
655 }
656
657
658
659 typedef struct xer_tmp_enc_s {
660         void *buffer;
661         size_t offset;
662         size_t size;
663 } xer_tmp_enc_t;
664 static int
665 SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) {
666         xer_tmp_enc_t *t = (xer_tmp_enc_t *)key;
667         if(t->offset + size >= t->size) {
668                 size_t newsize = (t->size << 2) + size;
669                 void *p = REALLOC(t->buffer, newsize);
670                 if(!p) return -1;
671                 t->buffer = p;
672                 t->size = newsize;
673         }
674         memcpy((char *)t->buffer + t->offset, buffer, size);
675         t->offset += size;
676         return 0;
677 }
678 static int
679 SET_OF_xer_order(const void *aptr, const void *bptr) {
680         const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr;
681         const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr;
682         size_t minlen = a->offset;
683         int ret;
684         if(b->offset < minlen) minlen = b->offset;
685         /* Well-formed UTF-8 has this nice lexicographical property... */
686         ret = memcmp(a->buffer, b->buffer, minlen);
687         if(ret != 0) return ret;
688         if(a->offset == b->offset)
689                 return 0;
690         if(a->offset == minlen)
691                 return -1;
692         return 1;
693 }
694
695
696 asn_enc_rval_t
697 SET_OF_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
698                   enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
699                   void *app_key) {
700     asn_enc_rval_t er;
701         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
702         const asn_TYPE_member_t *elm = td->elements;
703     const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
704     const char *mname = specs->as_XMLValueList
705                 ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
706         size_t mlen = mname ? strlen(mname) : 0;
707         int xcan = (flags & XER_F_CANONICAL);
708         xer_tmp_enc_t *encs = 0;
709         size_t encs_count = 0;
710         void *original_app_key = app_key;
711         asn_app_consume_bytes_f *original_cb = cb;
712         int i;
713
714         if(!sptr) ASN__ENCODE_FAILED;
715
716         if(xcan) {
717                 encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
718                 if(!encs) ASN__ENCODE_FAILED;
719                 cb = SET_OF_encode_xer_callback;
720         }
721
722         er.encoded = 0;
723
724         for(i = 0; i < list->count; i++) {
725                 asn_enc_rval_t tmper;
726
727                 void *memb_ptr = list->array[i];
728                 if(!memb_ptr) continue;
729
730                 if(encs) {
731                         memset(&encs[encs_count], 0, sizeof(encs[0]));
732                         app_key = &encs[encs_count];
733                         encs_count++;
734                 }
735
736                 if(mname) {
737                         if(!xcan) ASN__TEXT_INDENT(1, ilevel);
738                         ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
739                 }
740
741                 if(!xcan && specs->as_XMLValueList == 1)
742                         ASN__TEXT_INDENT(1, ilevel + 1);
743                 tmper = elm->type->op->xer_encoder(elm->type, memb_ptr,
744                                 ilevel + (specs->as_XMLValueList != 2),
745                                 flags, cb, app_key);
746                 if(tmper.encoded == -1) return tmper;
747                 er.encoded += tmper.encoded;
748                 if(tmper.encoded == 0 && specs->as_XMLValueList) {
749                         const char *name = elm->type->xml_tag;
750                         size_t len = strlen(name);
751                         ASN__CALLBACK3("<", 1, name, len, "/>", 2);
752                 }
753
754                 if(mname) {
755                         ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
756                 }
757
758         }
759
760         if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
761
762         if(encs) {
763                 xer_tmp_enc_t *enc = encs;
764                 xer_tmp_enc_t *end = encs + encs_count;
765                 ssize_t control_size = 0;
766
767                 er.encoded = 0;
768                 cb = original_cb;
769                 app_key = original_app_key;
770                 qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order);
771
772                 for(; enc < end; enc++) {
773                         ASN__CALLBACK(enc->buffer, enc->offset);
774                         FREEMEM(enc->buffer);
775                         enc->buffer = 0;
776                         control_size += enc->offset;
777                 }
778                 assert(control_size == er.encoded);
779         }
780
781         goto cleanup;
782 cb_failed:
783         ASN__ENCODE_FAILED;
784 cleanup:
785         if(encs) {
786                 size_t n;
787                 for(n = 0; n < encs_count; n++) {
788                         FREEMEM(encs[n].buffer);
789                 }
790                 FREEMEM(encs);
791         }
792         ASN__ENCODED_OK(er);
793 }
794
795 int
796 SET_OF_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
797              asn_app_consume_bytes_f *cb, void *app_key) {
798     asn_TYPE_member_t *elm = td->elements;
799         const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
800         int ret;
801         int i;
802
803         if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
804
805         /* Dump preamble */
806         if(cb(td->name, strlen(td->name), app_key) < 0
807         || cb(" ::= {", 6, app_key) < 0)
808                 return -1;
809
810         for(i = 0; i < list->count; i++) {
811                 const void *memb_ptr = list->array[i];
812                 if(!memb_ptr) continue;
813
814                 _i_INDENT(1);
815
816                 ret = elm->type->op->print_struct(elm->type, memb_ptr,
817                         ilevel + 1, cb, app_key);
818                 if(ret) return ret;
819         }
820
821         ilevel--;
822         _i_INDENT(1);
823
824         return (cb("}", 1, app_key) < 0) ? -1 : 0;
825 }
826
827 void
828 SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr,
829             enum asn_struct_free_method method) {
830     if(td && ptr) {
831                 const asn_SET_OF_specifics_t *specs;
832                 asn_TYPE_member_t *elm = td->elements;
833                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
834                 asn_struct_ctx_t *ctx;  /* Decoder context */
835                 int i;
836
837                 /*
838                  * Could not use set_of_empty() because of (*free)
839                  * incompatibility.
840                  */
841                 for(i = 0; i < list->count; i++) {
842                         void *memb_ptr = list->array[i];
843                         if(memb_ptr)
844                         ASN_STRUCT_FREE(*elm->type, memb_ptr);
845                 }
846                 list->count = 0;        /* No meaningful elements left */
847
848                 asn_set_empty(list);    /* Remove (list->array) */
849
850                 specs = (const asn_SET_OF_specifics_t *)td->specifics;
851                 ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
852                 if(ctx->ptr) {
853                         ASN_STRUCT_FREE(*elm->type, ctx->ptr);
854                         ctx->ptr = 0;
855                 }
856
857         switch(method) {
858         case ASFM_FREE_EVERYTHING:
859             FREEMEM(ptr);
860             break;
861         case ASFM_FREE_UNDERLYING:
862             break;
863         case ASFM_FREE_UNDERLYING_AND_RESET:
864             memset(ptr, 0, specs->struct_size);
865             break;
866         }
867     }
868 }
869
870 int
871 SET_OF_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
872                   asn_app_constraint_failed_f *ctfailcb, void *app_key) {
873     const asn_TYPE_member_t *elm = td->elements;
874         asn_constr_check_f *constr;
875         const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
876         int i;
877
878         if(!sptr) {
879                 ASN__CTFAIL(app_key, td, sptr,
880                         "%s: value not given (%s:%d)",
881                         td->name, __FILE__, __LINE__);
882                 return -1;
883         }
884
885         constr = elm->encoding_constraints.general_constraints;
886         if(!constr) constr = elm->type->encoding_constraints.general_constraints;
887
888         /*
889          * Iterate over the members of an array.
890          * Validate each in turn, until one fails.
891          */
892         for(i = 0; i < list->count; i++) {
893                 const void *memb_ptr = list->array[i];
894                 int ret;
895
896                 if(!memb_ptr) continue;
897
898                 ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
899                 if(ret) return ret;
900         }
901
902         return 0;
903 }
904
905 #ifndef ASN_DISABLE_PER_SUPPORT
906
907 asn_dec_rval_t
908 SET_OF_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
909                    const asn_TYPE_descriptor_t *td,
910                    const asn_per_constraints_t *constraints, void **sptr,
911                    asn_per_data_t *pd) {
912     asn_dec_rval_t rv;
913         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
914     const asn_TYPE_member_t *elm = td->elements; /* Single one */
915     void *st = *sptr;
916         asn_anonymous_set_ *list;
917         const asn_per_constraint_t *ct;
918         int repeat = 0;
919         ssize_t nelems;
920
921         if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
922                 ASN__DECODE_FAILED;
923
924         /*
925          * Create the target structure if it is not present already.
926          */
927         if(!st) {
928                 st = *sptr = CALLOC(1, specs->struct_size);
929                 if(!st) ASN__DECODE_FAILED;
930         }                                                                       
931         list = _A_SET_FROM_VOID(st);
932
933         /* Figure out which constraints to use */
934         if(constraints) ct = &constraints->size;
935         else if(td->encoding_constraints.per_constraints)
936                 ct = &td->encoding_constraints.per_constraints->size;
937         else ct = 0;
938
939         if(ct && ct->flags & APC_EXTENSIBLE) {
940                 int value = per_get_few_bits(pd, 1);
941                 if(value < 0) ASN__DECODE_STARVED;
942                 if(value) ct = 0;       /* Not restricted! */
943         }
944
945         if(ct && ct->effective_bits >= 0) {
946                 /* X.691, #19.5: No length determinant */
947                 nelems = per_get_few_bits(pd, ct->effective_bits);
948                 ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
949                         (long)nelems, ct->lower_bound, td->name);
950                 if(nelems < 0)  ASN__DECODE_STARVED;
951                 nelems += ct->lower_bound;
952         } else {
953                 nelems = -1;
954         }
955
956         do {
957                 int i;
958                 if(nelems < 0) {
959                         nelems = uper_get_length(pd, -1, 0, &repeat);
960             ASN_DEBUG("Got to decode %" ASN_PRI_SSIZE " elements (eff %d)",
961                       nelems, (int)(ct ? ct->effective_bits : -1));
962             if(nelems < 0) ASN__DECODE_STARVED;
963                 }
964
965                 for(i = 0; i < nelems; i++) {
966                         void *ptr = 0;
967                         ASN_DEBUG("SET OF %s decoding", elm->type->name);
968                         rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
969                                 elm->encoding_constraints.per_constraints, &ptr, pd);
970                         ASN_DEBUG("%s SET OF %s decoded %d, %p",
971                                 td->name, elm->type->name, rv.code, ptr);
972                         if(rv.code == RC_OK) {
973                                 if(ASN_SET_ADD(list, ptr) == 0) {
974                     if(rv.consumed == 0 && nelems > 200) {
975                         /* Protect from SET OF NULL compression bombs. */
976                         ASN__DECODE_FAILED;
977                     }
978                                         continue;
979                 }
980                                 ASN_DEBUG("Failed to add element into %s",
981                                         td->name);
982                                 /* Fall through */
983                                 rv.code = RC_FAIL;
984                         } else {
985                                 ASN_DEBUG("Failed decoding %s of %s (SET OF)",
986                                         elm->type->name, td->name);
987                         }
988                         if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
989                         return rv;
990                 }
991
992                 nelems = -1;    /* Allow uper_get_length() */
993         } while(repeat);
994
995         ASN_DEBUG("Decoded %s as SET OF", td->name);
996
997         rv.code = RC_OK;
998         rv.consumed = 0;
999         return rv;
1000 }
1001
1002 asn_enc_rval_t
1003 SET_OF_encode_uper(const asn_TYPE_descriptor_t *td,
1004                    const asn_per_constraints_t *constraints, const void *sptr,
1005                    asn_per_outp_t *po) {
1006     const asn_anonymous_set_ *list;
1007     const asn_per_constraint_t *ct;
1008     const asn_TYPE_member_t *elm = td->elements;
1009     struct _el_buffer *encoded_els;
1010     asn_enc_rval_t er;
1011     size_t encoded_edx;
1012
1013     if(!sptr) ASN__ENCODE_FAILED;
1014
1015     list = _A_CSET_FROM_VOID(sptr);
1016
1017     er.encoded = 0;
1018
1019     ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
1020
1021     if(constraints) ct = &constraints->size;
1022     else if(td->encoding_constraints.per_constraints)
1023         ct = &td->encoding_constraints.per_constraints->size;
1024     else ct = 0;
1025
1026     /* If extensible constraint, check if size is in root */
1027     if(ct) {
1028         int not_in_root =
1029             (list->count < ct->lower_bound || list->count > ct->upper_bound);
1030         ASN_DEBUG("lb %ld ub %ld %s", ct->lower_bound, ct->upper_bound,
1031                   ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
1032         if(ct->flags & APC_EXTENSIBLE) {
1033             /* Declare whether size is in extension root */
1034             if(per_put_few_bits(po, not_in_root, 1)) ASN__ENCODE_FAILED;
1035             if(not_in_root) ct = 0;
1036         } else if(not_in_root && ct->effective_bits >= 0) {
1037             ASN__ENCODE_FAILED;
1038         }
1039
1040     }
1041
1042     if(ct && ct->effective_bits >= 0) {
1043         /* X.691, #19.5: No length determinant */
1044         if(per_put_few_bits(po, list->count - ct->lower_bound,
1045                             ct->effective_bits))
1046             ASN__ENCODE_FAILED;
1047     } else if(list->count == 0) {
1048         /* When the list is empty add only the length determinant
1049          * X.691, #20.6 and #11.9.4.1
1050          */
1051         if (uper_put_length(po, 0, 0)) {
1052             ASN__ENCODE_FAILED;
1053         }
1054         ASN__ENCODED_OK(er);
1055     }
1056
1057
1058     /*
1059      * Canonical UPER #22.1 mandates dynamic sorting of the SET OF elements
1060      * according to their encodings. Build an array of the encoded elements.
1061      */
1062     encoded_els = SET_OF__encode_sorted(elm, list, SOES_CUPER);
1063
1064     for(encoded_edx = 0; (ssize_t)encoded_edx < list->count;) {
1065         ssize_t may_encode;
1066         size_t edx;
1067         int need_eom = 0;
1068
1069         if(ct && ct->effective_bits >= 0) {
1070             may_encode = list->count;
1071         } else {
1072             may_encode =
1073                 uper_put_length(po, list->count - encoded_edx, &need_eom);
1074             if(may_encode < 0) ASN__ENCODE_FAILED;
1075         }
1076
1077         for(edx = encoded_edx; edx < encoded_edx + may_encode; edx++) {
1078             const struct _el_buffer *el = &encoded_els[edx];
1079             if(asn_put_many_bits(po, el->buf,
1080                                  (8 * el->length) - el->bits_unused) < 0) {
1081                 break;
1082             }
1083         }
1084
1085         if(need_eom && uper_put_length(po, 0, 0))
1086             ASN__ENCODE_FAILED; /* End of Message length */
1087
1088         encoded_edx += may_encode;
1089     }
1090
1091     SET_OF__encode_sorted_free(encoded_els, list->count);
1092
1093     if((ssize_t)encoded_edx == list->count) {
1094         ASN__ENCODED_OK(er);
1095     } else {
1096         ASN__ENCODE_FAILED;
1097     }
1098 }
1099
1100
1101 #endif  /* ASN_DISABLE_PER_SUPPORT */
1102
1103 struct comparable_ptr {
1104     const asn_TYPE_descriptor_t *td;
1105     const void *sptr;
1106 };
1107
1108 static int
1109 SET_OF__compare_cb(const void *aptr, const void *bptr) {
1110     const struct comparable_ptr *a = aptr;
1111     const struct comparable_ptr *b = bptr;
1112     assert(a->td == b->td);
1113     return a->td->op->compare_struct(a->td, a->sptr, b->sptr);
1114 }
1115
1116 int
1117 SET_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
1118                const void *bptr) {
1119     const asn_anonymous_set_ *a = _A_CSET_FROM_VOID(aptr);
1120     const asn_anonymous_set_ *b = _A_CSET_FROM_VOID(bptr);
1121
1122     if(a && b) {
1123         struct comparable_ptr *asorted;
1124         struct comparable_ptr *bsorted;
1125         ssize_t common_length;
1126         ssize_t idx;
1127
1128         if(a->count == 0) {
1129             if(b->count) return -1;
1130             return 0;
1131         } else if(b->count == 0) {
1132             return 1;
1133         }
1134
1135         asorted = MALLOC(a->count * sizeof(asorted[0]));
1136         bsorted = MALLOC(b->count * sizeof(bsorted[0]));
1137         if(!asorted || !bsorted) {
1138             FREEMEM(asorted);
1139             FREEMEM(bsorted);
1140             return -1;
1141         }
1142
1143         for(idx = 0; idx < a->count; idx++) {
1144             asorted[idx].td = td->elements->type;
1145             asorted[idx].sptr = a->array[idx];
1146         }
1147
1148         for(idx = 0; idx < b->count; idx++) {
1149             bsorted[idx].td = td->elements->type;
1150             bsorted[idx].sptr = b->array[idx];
1151         }
1152
1153         qsort(asorted, a->count, sizeof(asorted[0]), SET_OF__compare_cb);
1154         qsort(bsorted, b->count, sizeof(bsorted[0]), SET_OF__compare_cb);
1155
1156         common_length = (a->count < b->count ? a->count : b->count);
1157         for(idx = 0; idx < common_length; idx++) {
1158             int ret = td->elements->type->op->compare_struct(
1159                 td->elements->type, asorted[idx].sptr, bsorted[idx].sptr);
1160             if(ret) {
1161                 FREEMEM(asorted);
1162                 FREEMEM(bsorted);
1163                 return ret;
1164             }
1165         }
1166
1167         FREEMEM(asorted);
1168         FREEMEM(bsorted);
1169
1170         if(idx < b->count) /* more elements in b */
1171             return -1;     /* a is shorter, so put it first */
1172         if(idx < a->count) return 1;
1173     } else if(!a) {
1174         return -1;
1175     } else if(!b) {
1176         return 1;
1177     }
1178
1179         return 0;
1180 }
1181
1182
1183 asn_TYPE_operation_t asn_OP_SET_OF = {
1184         SET_OF_free,
1185         SET_OF_print,
1186         SET_OF_compare,
1187         SET_OF_decode_ber,
1188         SET_OF_encode_der,
1189         SET_OF_decode_xer,
1190         SET_OF_encode_xer,
1191 #ifdef ASN_DISABLE_OER_SUPPORT
1192         0,
1193         0,
1194 #else
1195         SET_OF_decode_oer,
1196         SET_OF_encode_oer,
1197 #endif
1198 #ifdef ASN_DISABLE_PER_SUPPORT
1199         0,
1200         0,
1201 #else
1202         SET_OF_decode_uper,
1203         SET_OF_encode_uper,
1204 #endif /* ASN_DISABLE_PER_SUPPORT */
1205         SET_OF_random_fill,
1206         0       /* Use generic outmost tag fetcher */
1207 };
1208
1209
1210 asn_random_fill_result_t
1211 SET_OF_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
1212                    const asn_encoding_constraints_t *constraints,
1213                    size_t max_length) {
1214     const asn_SET_OF_specifics_t *specs =
1215         (const asn_SET_OF_specifics_t *)td->specifics;
1216     asn_random_fill_result_t res_ok = {ARFILL_OK, 0};
1217     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
1218     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
1219     const asn_TYPE_member_t *elm = td->elements;
1220     void *st = *sptr;
1221     long max_elements = 5;
1222     long slb = 0;   /* Lower size bound */
1223     long sub = 0;   /* Upper size bound */
1224     size_t rnd_len;
1225
1226     if(max_length == 0) return result_skipped;
1227
1228     if(st == NULL) {
1229         st = (*sptr = CALLOC(1, specs->struct_size));
1230         if(st == NULL) {
1231             return result_failed;
1232         }
1233     }
1234
1235     switch(asn_random_between(0, 6)) {
1236     case 0: max_elements = 0; break;
1237     case 1: max_elements = 1; break;
1238     case 2: max_elements = 5; break;
1239     case 3: max_elements = max_length; break;
1240     case 4: max_elements = max_length / 2; break;
1241     case 5: max_elements = max_length / 4; break;
1242     default: break;
1243     }
1244     sub = slb + max_elements;
1245
1246     if(!constraints || !constraints->per_constraints)
1247         constraints = &td->encoding_constraints;
1248     if(constraints->per_constraints) {
1249         const asn_per_constraint_t *pc = &constraints->per_constraints->size;
1250         if(pc->flags & APC_SEMI_CONSTRAINED) {
1251             slb = pc->lower_bound;
1252             sub = pc->lower_bound + max_elements;
1253         } else if(pc->flags & APC_CONSTRAINED) {
1254             slb = pc->lower_bound;
1255             sub = pc->upper_bound;
1256             if(sub - slb > max_elements) sub = slb + max_elements;
1257         }
1258     }
1259
1260     /* Bias towards edges of allowed space */
1261     switch(asn_random_between(-1, 4)) {
1262     default:
1263     case -1:
1264         /* Prepare lengths somewhat outside of constrained range. */
1265         if(constraints->per_constraints
1266            && (constraints->per_constraints->size.flags & APC_EXTENSIBLE)) {
1267             switch(asn_random_between(0, 5)) {
1268             default:
1269             case 0:
1270                 rnd_len = 0;
1271                 break;
1272             case 1:
1273                 if(slb > 0) {
1274                     rnd_len = slb - 1;
1275                 } else {
1276                     rnd_len = 0;
1277                 }
1278                 break;
1279             case 2:
1280                 rnd_len = asn_random_between(0, slb);
1281                 break;
1282             case 3:
1283                 if(sub < (ssize_t)max_length) {
1284                     rnd_len = sub + 1;
1285                 } else {
1286                     rnd_len = max_length;
1287                 }
1288                 break;
1289             case 4:
1290                 if(sub < (ssize_t)max_length) {
1291                     rnd_len = asn_random_between(sub + 1, max_length);
1292                 } else {
1293                     rnd_len = max_length;
1294                 }
1295                 break;
1296             case 5:
1297                 rnd_len = max_length;
1298                 break;
1299             }
1300             break;
1301         }
1302         /* Fall through */
1303     case 0:
1304         rnd_len = asn_random_between(slb, sub);
1305         break;
1306     case 1:
1307         if(slb < sub) {
1308             rnd_len = asn_random_between(slb + 1, sub);
1309             break;
1310         }
1311         /* Fall through */
1312     case 2:
1313         rnd_len = asn_random_between(slb, slb);
1314         break;
1315     case 3:
1316         if(slb < sub) {
1317             rnd_len = asn_random_between(slb, sub - 1);
1318             break;
1319         }
1320         /* Fall through */
1321     case 4:
1322         rnd_len = asn_random_between(sub, sub);
1323         break;
1324     }
1325
1326     for(; rnd_len > 0; rnd_len--) {
1327         asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
1328         void *ptr = 0;
1329         asn_random_fill_result_t tmpres = elm->type->op->random_fill(
1330             elm->type, &ptr, &elm->encoding_constraints,
1331             (max_length > res_ok.length ? max_length - res_ok.length : 0)
1332                 / rnd_len);
1333         switch(tmpres.code) {
1334         case ARFILL_OK:
1335             ASN_SET_ADD(list, ptr);
1336             res_ok.length += tmpres.length;
1337             break;
1338         case ARFILL_SKIPPED:
1339             break;
1340         case ARFILL_FAILED:
1341             assert(ptr == 0);
1342             return tmpres;
1343         }
1344     }
1345
1346     return res_ok;
1347 }
1348