1 /*
2  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include "asn1/asn1c/asn_internal.h"
6 #include "asn1/asn1c/constr_CHOICE.h"
7 #include "asn1/asn1c/per_opentype.h"
8 
9 /*
10  * Number of bytes left for this structure.
11  * (ctx->left) indicates the number of bytes _transferred_ for the structure.
12  * (size) contains the number of bytes in the buffer passed.
13  */
14 #define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
15 
16 /*
17  * If the subprocessor function returns with an indication that it wants
18  * more data, it may well be a fatal decoding problem, because the
19  * size is constrained by the <TLV>'s L, even if the buffer size allows
20  * reading more data.
21  * For example, consider the buffer containing the following TLVs:
22  * <T:5><L:1><V> <T:6>...
23  * The TLV length clearly indicates that one byte is expected in V, but
24  * if the V processor returns with "want more data" even if the buffer
25  * contains way more data than the V processor have seen.
26  */
27 #define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
28 
29 /*
30  * This macro "eats" the part of the buffer which is definitely "consumed",
31  * i.e. was correctly converted into local representation or rightfully skipped.
32  */
33 #undef	ADVANCE
34 #define	ADVANCE(num_bytes)	do {		\
35 		size_t num = num_bytes;		\
36 		ptr = ((const char *)ptr) + num;\
37 		size -= num;			\
38 		if(ctx->left >= 0)		\
39 			ctx->left -= num;	\
40 		consumed_myself += num;		\
41 	} while(0)
42 
43 /*
44  * Switch to the next phase of parsing.
45  */
46 #undef	NEXT_PHASE
47 #define	NEXT_PHASE(ctx)	do {			\
48 		ctx->phase++;			\
49 		ctx->step = 0;			\
50 	} while(0)
51 
52 /*
53  * Return a standardized complex structure.
54  */
55 #undef	RETURN
56 #define	RETURN(_code)	do {			\
57 		rval.code = _code;		\
58 		rval.consumed = consumed_myself;\
59 		return rval;			\
60 	} while(0)
61 
62 /*
63  * See the definitions.
64  */
65 static unsigned _fetch_present_idx(const void *struct_ptr, unsigned off,
66                                    unsigned size);
67 static void _set_present_idx(void *sptr, unsigned offset, unsigned size,
68                              unsigned pres);
69 static const void *_get_member_ptr(const asn_TYPE_descriptor_t *,
70                                    const void *sptr, asn_TYPE_member_t **elm,
71                                    unsigned *present);
72 
73 /*
74  * Tags are canonically sorted in the tag to member table.
75  */
76 static int
_search4tag(const void * ap,const void * bp)77 _search4tag(const void *ap, const void *bp) {
78 	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
79 	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
80 
81 	int a_class = BER_TAG_CLASS(a->el_tag);
82 	int b_class = BER_TAG_CLASS(b->el_tag);
83 
84 	if(a_class == b_class) {
85 		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
86 		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
87 
88 		if(a_value == b_value)
89 			return 0;
90 		else if(a_value < b_value)
91 			return -1;
92 		else
93 			return 1;
94 	} else if(a_class < b_class) {
95 		return -1;
96 	} else {
97 		return 1;
98 	}
99 }
100 
101 /*
102  * The decoder of the CHOICE type.
103  */
104 asn_dec_rval_t
CHOICE_decode_ber(const asn_codec_ctx_t * opt_codec_ctx,const asn_TYPE_descriptor_t * td,void ** struct_ptr,const void * ptr,size_t size,int tag_mode)105 CHOICE_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
106                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
107                   const void *ptr, size_t size, int tag_mode) {
108     /*
109 	 * Bring closer parts of structure description.
110 	 */
111 	const asn_CHOICE_specifics_t *specs =
112 		(const asn_CHOICE_specifics_t *)td->specifics;
113 	asn_TYPE_member_t *elements = td->elements;
114 
115 	/*
116 	 * Parts of the structure being constructed.
117 	 */
118 	void *st = *struct_ptr;	/* Target structure. */
119 	asn_struct_ctx_t *ctx;	/* Decoder context */
120 
121 	ber_tlv_tag_t tlv_tag;	/* T from TLV */
122 	ssize_t tag_len;	/* Length of TLV's T */
123 	asn_dec_rval_t rval;	/* Return code from subparsers */
124 
125 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
126 
127 	ASN_DEBUG("Decoding %s as CHOICE", td->name);
128 
129 	/*
130 	 * Create the target structure if it is not present already.
131 	 */
132 	if(st == 0) {
133 		st = *struct_ptr = CALLOC(1, specs->struct_size);
134 		if(st == 0) {
135 			RETURN(RC_FAIL);
136 		}
137 	}
138 
139 	/*
140 	 * Restore parsing context.
141 	 */
142 	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
143 
144 	/*
145 	 * Start to parse where left previously
146 	 */
147 	switch(ctx->phase) {
148 	case 0:
149 		/*
150 		 * PHASE 0.
151 		 * Check that the set of tags associated with given structure
152 		 * perfectly fits our expectations.
153 		 */
154 
155 		if(tag_mode || td->tags_count) {
156 			rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
157 				tag_mode, -1, &ctx->left, 0);
158 			if(rval.code != RC_OK) {
159 				ASN_DEBUG("%s tagging check failed: %d",
160 					td->name, rval.code);
161 				return rval;
162 			}
163 
164 			if(ctx->left >= 0) {
165 				/* ?Substracted below! */
166 				ctx->left += rval.consumed;
167 			}
168 			ADVANCE(rval.consumed);
169 		} else {
170 			ctx->left = -1;
171 		}
172 
173 		NEXT_PHASE(ctx);
174 
175 		ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
176 			(long)ctx->left, (long)size);
177 
178 		/* Fall through */
179 	case 1:
180 		/*
181 		 * Fetch the T from TLV.
182 		 */
183 		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
184 		ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
185 		switch(tag_len) {
186 		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
187 			/* Fall through */
188 		case -1: RETURN(RC_FAIL);
189 		}
190 
191 		do {
192 			const asn_TYPE_tag2member_t *t2m;
193 			asn_TYPE_tag2member_t key;
194 
195 			key.el_tag = tlv_tag;
196 			t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
197 					specs->tag2el, specs->tag2el_count,
198 					sizeof(specs->tag2el[0]), _search4tag);
199 			if(t2m) {
200 				/*
201 				 * Found the element corresponding to the tag.
202 				 */
203 				NEXT_PHASE(ctx);
204 				ctx->step = t2m->el_no;
205 				break;
206 			} else if(specs->ext_start == -1) {
207 				ASN_DEBUG("Unexpected tag %s "
208 					"in non-extensible CHOICE %s",
209 					ber_tlv_tag_string(tlv_tag), td->name);
210 				RETURN(RC_FAIL);
211 			} else {
212 				/* Skip this tag */
213 				ssize_t skip;
214 
215 				ASN_DEBUG("Skipping unknown tag %s",
216 					ber_tlv_tag_string(tlv_tag));
217 
218 				skip = ber_skip_length(opt_codec_ctx,
219 					BER_TLV_CONSTRUCTED(ptr),
220 					(const char *)ptr + tag_len,
221 					LEFT - tag_len);
222 
223 				switch(skip) {
224 				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
225 					/* Fall through */
226 				case -1: RETURN(RC_FAIL);
227 				}
228 
229 				ADVANCE(skip + tag_len);
230 				RETURN(RC_OK);
231 			}
232 		} while(0);
233 
234 	case 2:
235 		/*
236 		 * PHASE 2.
237 		 * Read in the element.
238 		 */
239 	    do {
240 		asn_TYPE_member_t *elm;/* CHOICE's element */
241 		void *memb_ptr;		/* Pointer to the member */
242 		void **memb_ptr2;	/* Pointer to that pointer */
243 
244 		elm = &elements[ctx->step];
245 
246 		/*
247 		 * Compute the position of the member inside a structure,
248 		 * and also a type of containment (it may be contained
249 		 * as pointer or using inline inclusion).
250 		 */
251 		if(elm->flags & ATF_POINTER) {
252 			/* Member is a pointer to another structure */
253 			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
254 		} else {
255 			/*
256 			 * A pointer to a pointer
257 			 * holding the start of the structure
258 			 */
259 			memb_ptr = (char *)st + elm->memb_offset;
260 			memb_ptr2 = &memb_ptr;
261 		}
262 		/* Set presence to be able to free it properly at any time */
263 		_set_present_idx(st, specs->pres_offset,
264 				specs->pres_size, ctx->step + 1);
265 		/*
266 		 * Invoke the member fetch routine according to member's type
267 		 */
268 		rval = elm->type->op->ber_decoder(opt_codec_ctx, elm->type,
269 				memb_ptr2, ptr, LEFT, elm->tag_mode);
270 		switch(rval.code) {
271 		case RC_OK:
272 			break;
273 		case RC_WMORE: /* More data expected */
274 			if(!SIZE_VIOLATION) {
275 				ADVANCE(rval.consumed);
276 				RETURN(RC_WMORE);
277 			}
278 			RETURN(RC_FAIL);
279 		case RC_FAIL: /* Fatal error */
280 			RETURN(rval.code);
281 		} /* switch(rval) */
282 
283 		ADVANCE(rval.consumed);
284 	  } while(0);
285 
286 		NEXT_PHASE(ctx);
287 
288 		/* Fall through */
289 	case 3:
290 		ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
291 			td->name, (long)ctx->left, (long)size,
292 			tag_mode, td->tags_count);
293 
294 		if(ctx->left > 0) {
295 			/*
296 			 * The type must be fully decoded
297 			 * by the CHOICE member-specific decoder.
298 			 */
299 			RETURN(RC_FAIL);
300 		}
301 
302 		if(ctx->left == -1
303 		&& !(tag_mode || td->tags_count)) {
304 			/*
305 			 * This is an untagged CHOICE.
306 			 * It doesn't contain nothing
307 			 * except for the member itself, including all its tags.
308 			 * The decoding is completed.
309 			 */
310 			NEXT_PHASE(ctx);
311 			break;
312 		}
313 
314 		/*
315 		 * Read in the "end of data chunks"'s.
316 		 */
317 		while(ctx->left < 0) {
318 			ssize_t tl;
319 
320 			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
321 			switch(tl) {
322 			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
323 				/* Fall through */
324 			case -1: RETURN(RC_FAIL);
325 			}
326 
327 			/*
328 			 * Expected <0><0>...
329 			 */
330 			if(((const uint8_t *)ptr)[0] == 0) {
331 				if(LEFT < 2) {
332 					if(SIZE_VIOLATION)
333 						RETURN(RC_FAIL);
334 					else
335 						RETURN(RC_WMORE);
336 				} else if(((const uint8_t *)ptr)[1] == 0) {
337 					/*
338 					 * Correctly finished with <0><0>.
339 					 */
340 					ADVANCE(2);
341 					ctx->left++;
342 					continue;
343 				}
344 			} else {
345 				ASN_DEBUG("Unexpected continuation in %s",
346 					td->name);
347 				RETURN(RC_FAIL);
348 			}
349 
350 			/* UNREACHABLE */
351 		}
352 
353 		NEXT_PHASE(ctx);
354 	case 4:
355 		/* No meaningful work here */
356 		break;
357 	}
358 
359 	RETURN(RC_OK);
360 }
361 
362 asn_enc_rval_t
CHOICE_encode_der(const asn_TYPE_descriptor_t * td,const void * sptr,int tag_mode,ber_tlv_tag_t tag,asn_app_consume_bytes_f * cb,void * app_key)363 CHOICE_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
364                   int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
365                   void *app_key) {
366     const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
367 	asn_TYPE_member_t *elm;	/* CHOICE element */
368 	asn_enc_rval_t erval;
369 	const void *memb_ptr;
370 	size_t computed_size = 0;
371 	unsigned present;
372 
373 	if(!sptr) ASN__ENCODE_FAILED;
374 
375 	ASN_DEBUG("%s %s as CHOICE",
376 		cb?"Encoding":"Estimating", td->name);
377 
378 	present = _fetch_present_idx(sptr,
379 		specs->pres_offset, specs->pres_size);
380 
381 	/*
382 	 * If the structure was not initialized, it cannot be encoded:
383 	 * can't deduce what to encode in the choice type.
384 	 */
385 	if(present == 0 || present > td->elements_count) {
386 		if(present == 0 && td->elements_count == 0) {
387 			/* The CHOICE is empty?! */
388 			erval.encoded = 0;
389 			ASN__ENCODED_OK(erval);
390 		}
391 		ASN__ENCODE_FAILED;
392 	}
393 
394 	/*
395 	 * Seek over the present member of the structure.
396 	 */
397 	elm = &td->elements[present-1];
398 	if(elm->flags & ATF_POINTER) {
399         memb_ptr =
400             *(const void *const *)((const char *)sptr + elm->memb_offset);
401         if(memb_ptr == 0) {
402 			if(elm->optional) {
403 				erval.encoded = 0;
404 				ASN__ENCODED_OK(erval);
405 			}
406 			/* Mandatory element absent */
407 			ASN__ENCODE_FAILED;
408 		}
409 	} else {
410         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
411     }
412 
413 	/*
414 	 * If the CHOICE itself is tagged EXPLICIT:
415 	 * T ::= [2] EXPLICIT CHOICE { ... }
416 	 * Then emit the appropriate tags.
417 	 */
418 	if(tag_mode == 1 || td->tags_count) {
419 		/*
420 		 * For this, we need to pre-compute the member.
421 		 */
422 		ssize_t ret;
423 
424 		/* Encode member with its tag */
425 		erval = elm->type->op->der_encoder(elm->type, memb_ptr,
426 			elm->tag_mode, elm->tag, 0, 0);
427 		if(erval.encoded == -1)
428 			return erval;
429 
430 		/* Encode CHOICE with parent or my own tag */
431 		ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
432 			cb, app_key);
433 		if(ret == -1)
434 			ASN__ENCODE_FAILED;
435 		computed_size += ret;
436 	}
437 
438 	/*
439 	 * Encode the single underlying member.
440 	 */
441 	erval = elm->type->op->der_encoder(elm->type, memb_ptr,
442 		elm->tag_mode, elm->tag, cb, app_key);
443 	if(erval.encoded == -1)
444 		return erval;
445 
446 	ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
447 		(long)erval.encoded, (long)computed_size);
448 
449 	erval.encoded += computed_size;
450 
451 	return erval;
452 }
453 
454 ber_tlv_tag_t
CHOICE_outmost_tag(const asn_TYPE_descriptor_t * td,const void * ptr,int tag_mode,ber_tlv_tag_t tag)455 CHOICE_outmost_tag(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
456 	const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
457 	unsigned present;
458 
459 	assert(tag_mode == 0); (void)tag_mode;
460 	assert(tag == 0); (void)tag;
461 
462 	/*
463 	 * Figure out which CHOICE element is encoded.
464 	 */
465 	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
466 
467 	if(present > 0 && present <= td->elements_count) {
468 		const asn_TYPE_member_t *elm = &td->elements[present-1];
469 		const void *memb_ptr;
470 
471 		if(elm->flags & ATF_POINTER) {
472 			memb_ptr = *(const void * const *)
473 					((const char *)ptr + elm->memb_offset);
474 		} else {
475 			memb_ptr = (const void *)
476 					((const char *)ptr + elm->memb_offset);
477 		}
478 
479 		return asn_TYPE_outmost_tag(elm->type, memb_ptr,
480 			elm->tag_mode, elm->tag);
481 	} else {
482 		return (ber_tlv_tag_t)-1;
483 	}
484 }
485 
486 int
CHOICE_constraint(const asn_TYPE_descriptor_t * td,const void * sptr,asn_app_constraint_failed_f * ctfailcb,void * app_key)487 CHOICE_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
488                   asn_app_constraint_failed_f *ctfailcb, void *app_key) {
489     const asn_CHOICE_specifics_t *specs =
490         (const asn_CHOICE_specifics_t *)td->specifics;
491     unsigned present;
492 
493 	if(!sptr) {
494 		ASN__CTFAIL(app_key, td, sptr,
495 			"%s: value not given (%s:%d)",
496 			td->name, __FILE__, __LINE__);
497 		return -1;
498 	}
499 
500 	/*
501 	 * Figure out which CHOICE element is encoded.
502 	 */
503 	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
504 	if(present > 0 && present <= td->elements_count) {
505 		asn_TYPE_member_t *elm = &td->elements[present-1];
506 		const void *memb_ptr;
507 
508 		if(elm->flags & ATF_POINTER) {
509 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
510 			if(!memb_ptr) {
511 				if(elm->optional)
512 					return 0;
513 				ASN__CTFAIL(app_key, td, sptr,
514 					"%s: mandatory CHOICE element %s absent (%s:%d)",
515 					td->name, elm->name, __FILE__, __LINE__);
516 				return -1;
517 			}
518 		} else {
519 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
520 		}
521 
522 		if(elm->encoding_constraints.general_constraints) {
523 			return elm->encoding_constraints.general_constraints(elm->type, memb_ptr,
524 				ctfailcb, app_key);
525 		} else {
526 			return elm->type->encoding_constraints.general_constraints(elm->type,
527 					memb_ptr, ctfailcb, app_key);
528 		}
529 	} else {
530 		ASN__CTFAIL(app_key, td, sptr,
531 			"%s: no CHOICE element given (%s:%d)",
532 			td->name, __FILE__, __LINE__);
533 		return -1;
534 	}
535 }
536 
537 #undef	XER_ADVANCE
538 #define	XER_ADVANCE(num_bytes)	do {			\
539 		size_t num = num_bytes;			\
540 		buf_ptr = (const void *)(((const char *)buf_ptr) + num); \
541 		size -= num;				\
542 		consumed_myself += num;			\
543 	} while(0)
544 
545 /*
546  * Decode the XER (XML) data.
547  */
548 asn_dec_rval_t
CHOICE_decode_xer(const asn_codec_ctx_t * opt_codec_ctx,const asn_TYPE_descriptor_t * td,void ** struct_ptr,const char * opt_mname,const void * buf_ptr,size_t size)549 CHOICE_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
550                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
551                   const char *opt_mname, const void *buf_ptr, size_t size) {
552     /*
553 	 * Bring closer parts of structure description.
554 	 */
555 	const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
556 	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
557 
558 	/*
559 	 * Parts of the structure being constructed.
560 	 */
561 	void *st = *struct_ptr;	/* Target structure. */
562 	asn_struct_ctx_t *ctx;	/* Decoder context */
563 
564 	asn_dec_rval_t rval;		/* Return value of a decoder */
565 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
566 	size_t edx;			/* Element index */
567 
568 	/*
569 	 * Create the target structure if it is not present already.
570 	 */
571 	if(st == 0) {
572 		st = *struct_ptr = CALLOC(1, specs->struct_size);
573 		if(st == 0) RETURN(RC_FAIL);
574 	}
575 
576 	/*
577 	 * Restore parsing context.
578 	 */
579 	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
580 	if(ctx->phase == 0 && !*xml_tag)
581 		ctx->phase = 1;	/* Skip the outer tag checking phase */
582 
583 	/*
584 	 * Phases of XER/XML processing:
585 	 * Phase 0: Check that the opening tag matches our expectations.
586 	 * Phase 1: Processing body and reacting on closing tag.
587 	 * Phase 2: Processing inner type.
588 	 * Phase 3: Only waiting for closing tag.
589 	 * Phase 4: Skipping unknown extensions.
590 	 * Phase 5: PHASED OUT
591 	 */
592 	for(edx = ctx->step; ctx->phase <= 4;) {
593 		pxer_chunk_type_e ch_type;	/* XER chunk type */
594 		ssize_t ch_size;		/* Chunk size */
595 		xer_check_tag_e tcv;		/* Tag check value */
596 		asn_TYPE_member_t *elm;
597 
598 		/*
599 		 * Go inside the member.
600 		 */
601 		if(ctx->phase == 2) {
602 			asn_dec_rval_t tmprval;
603 			void *memb_ptr;		/* Pointer to the member */
604 			void **memb_ptr2;	/* Pointer to that pointer */
605 			unsigned old_present;
606 
607 			elm = &td->elements[edx];
608 
609 			if(elm->flags & ATF_POINTER) {
610 				/* Member is a pointer to another structure */
611 				memb_ptr2 = (void **)((char *)st
612 					+ elm->memb_offset);
613 			} else {
614 				memb_ptr = (char *)st + elm->memb_offset;
615 				memb_ptr2 = &memb_ptr;
616 			}
617 
618 			/* Start/Continue decoding the inner member */
619 			tmprval = elm->type->op->xer_decoder(opt_codec_ctx,
620 					elm->type, memb_ptr2, elm->name,
621 					buf_ptr, size);
622 			XER_ADVANCE(tmprval.consumed);
623 			ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
624 				elm->type->name, tmprval.code);
625 			old_present = _fetch_present_idx(st,
626 				specs->pres_offset, specs->pres_size);
627 			assert(old_present == 0 || old_present == edx + 1);
628 			/* Record what we've got */
629 			_set_present_idx(st,
630 				specs->pres_offset, specs->pres_size, edx + 1);
631 			if(tmprval.code != RC_OK)
632 				RETURN(tmprval.code);
633 			ctx->phase = 3;
634 			/* Fall through */
635 		}
636 
637 		/* No need to wait for closing tag; special mode. */
638 		if(ctx->phase == 3 && !*xml_tag) {
639 			ctx->phase = 5;	/* Phase out */
640 			RETURN(RC_OK);
641 		}
642 
643 		/*
644 		 * Get the next part of the XML stream.
645 		 */
646 		ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type);
647 		if(ch_size == -1) {
648             RETURN(RC_FAIL);
649         } else {
650 			switch(ch_type) {
651 			case PXER_WMORE:
652                 RETURN(RC_WMORE);
653 			case PXER_COMMENT:	/* Got XML comment */
654 			case PXER_TEXT:		/* Ignore free-standing text */
655 				XER_ADVANCE(ch_size);	/* Skip silently */
656 				continue;
657 			case PXER_TAG:
658 				break;	/* Check the rest down there */
659 			}
660 		}
661 
662 		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
663 		ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
664 			ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
665 			ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
666 			ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
667 			ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
668 		xml_tag, tcv);
669 
670 		/* Skip the extensions section */
671 		if(ctx->phase == 4) {
672 			ASN_DEBUG("skip_unknown(%d, %ld)",
673 				tcv, (long)ctx->left);
674 			switch(xer_skip_unknown(tcv, &ctx->left)) {
675 			case -1:
676 				ctx->phase = 5;
677 				RETURN(RC_FAIL);
678 			case 1:
679 				ctx->phase = 3;
680 				/* Fall through */
681 			case 0:
682 				XER_ADVANCE(ch_size);
683 				continue;
684 			case 2:
685 				ctx->phase = 3;
686 				break;
687 			}
688 		}
689 
690 		switch(tcv) {
691 		case XCT_BOTH:
692 			break;	/* No CHOICE? */
693 		case XCT_CLOSING:
694 			if(ctx->phase != 3)
695 				break;
696 			XER_ADVANCE(ch_size);
697 			ctx->phase = 5;	/* Phase out */
698 			RETURN(RC_OK);
699 		case XCT_OPENING:
700 			if(ctx->phase == 0) {
701 				XER_ADVANCE(ch_size);
702 				ctx->phase = 1;	/* Processing body phase */
703 				continue;
704 			}
705 			/* Fall through */
706 		case XCT_UNKNOWN_OP:
707 		case XCT_UNKNOWN_BO:
708 
709 			if(ctx->phase != 1)
710 				break;	/* Really unexpected */
711 
712 			/*
713 			 * Search which inner member corresponds to this tag.
714 			 */
715 			for(edx = 0; edx < td->elements_count; edx++) {
716 				elm = &td->elements[edx];
717 				tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
718 				switch(tcv) {
719 				case XCT_BOTH:
720 				case XCT_OPENING:
721 					/*
722 					 * Process this member.
723 					 */
724 					ctx->step = edx;
725 					ctx->phase = 2;
726 					break;
727 				case XCT_UNKNOWN_OP:
728 				case XCT_UNKNOWN_BO:
729 					continue;
730 				default:
731 					edx = td->elements_count;
732 					break;	/* Phase out */
733 				}
734 				break;
735 			}
736 			if(edx != td->elements_count)
737 				continue;
738 
739 			/* It is expected extension */
740 			if(specs->ext_start != -1) {
741 				ASN_DEBUG("Got anticipated extension");
742 				/*
743 				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
744 				 * By using a mask. Only record a pure
745 				 * <opening> tags.
746 				 */
747 				if(tcv & XCT_CLOSING) {
748 					/* Found </extension> without body */
749 					ctx->phase = 3; /* Terminating */
750 				} else {
751 					ctx->left = 1;
752 					ctx->phase = 4; /* Skip ...'s */
753 				}
754 				XER_ADVANCE(ch_size);
755 				continue;
756 			}
757 
758 			/* Fall through */
759 		default:
760 			break;
761 		}
762 
763 		ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
764 			" (ph=%d, tag=%s)",
765 			ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
766 			ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
767 			ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
768 			ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
769 			td->name, ctx->phase, xml_tag);
770 		break;
771 	}
772 
773 	ctx->phase = 5;	/* Phase out, just in case */
774 	RETURN(RC_FAIL);
775 }
776 
777 
778 asn_enc_rval_t
CHOICE_encode_xer(const asn_TYPE_descriptor_t * td,const void * sptr,int ilevel,enum xer_encoder_flags_e flags,asn_app_consume_bytes_f * cb,void * app_key)779 CHOICE_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
780                   enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
781                   void *app_key) {
782     const asn_CHOICE_specifics_t *specs =
783         (const asn_CHOICE_specifics_t *)td->specifics;
784     asn_enc_rval_t er;
785 	unsigned present;
786 
787 	if(!sptr)
788 		ASN__ENCODE_FAILED;
789 
790 	/*
791 	 * Figure out which CHOICE element is encoded.
792 	 */
793 	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
794 
795 	if(present == 0 || present > td->elements_count) {
796 		ASN__ENCODE_FAILED;
797 	}  else {
798 		asn_enc_rval_t tmper;
799 		asn_TYPE_member_t *elm = &td->elements[present-1];
800 		const void *memb_ptr;
801 		const char *mname = elm->name;
802 		unsigned int mlen = strlen(mname);
803 
804 		if(elm->flags & ATF_POINTER) {
805             memb_ptr =
806                 *(const void *const *)((const char *)sptr + elm->memb_offset);
807             if(!memb_ptr) ASN__ENCODE_FAILED;
808 		} else {
809             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
810         }
811 
812         er.encoded = 0;
813 
814 		if(!(flags & XER_F_CANONICAL)) ASN__TEXT_INDENT(1, ilevel);
815 		ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
816 
817 		tmper = elm->type->op->xer_encoder(elm->type, memb_ptr,
818 				ilevel + 1, flags, cb, app_key);
819 		if(tmper.encoded == -1) return tmper;
820 		er.encoded += tmper.encoded;
821 
822 		ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
823 	}
824 
825 	if(!(flags & XER_F_CANONICAL)) ASN__TEXT_INDENT(1, ilevel - 1);
826 
827 	ASN__ENCODED_OK(er);
828 cb_failed:
829 	ASN__ENCODE_FAILED;
830 }
831 
832 asn_dec_rval_t
CHOICE_decode_uper(const asn_codec_ctx_t * opt_codec_ctx,const asn_TYPE_descriptor_t * td,const asn_per_constraints_t * constraints,void ** sptr,asn_per_data_t * pd)833 CHOICE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
834                    const asn_TYPE_descriptor_t *td,
835                    const asn_per_constraints_t *constraints, void **sptr,
836                    asn_per_data_t *pd) {
837     const asn_CHOICE_specifics_t *specs =
838         (const asn_CHOICE_specifics_t *)td->specifics;
839     asn_dec_rval_t rv;
840 	const asn_per_constraint_t *ct;
841 	asn_TYPE_member_t *elm;	/* CHOICE's element */
842 	void *memb_ptr;
843 	void **memb_ptr2;
844 	void *st = *sptr;
845 	int value;
846 
847 	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
848 		ASN__DECODE_FAILED;
849 
850 	/*
851 	 * Create the target structure if it is not present already.
852 	 */
853 	if(!st) {
854 		st = *sptr = CALLOC(1, specs->struct_size);
855 		if(!st) ASN__DECODE_FAILED;
856 	}
857 
858 	if(constraints) ct = &constraints->value;
859 	else if(td->encoding_constraints.per_constraints) ct = &td->encoding_constraints.per_constraints->value;
860 	else ct = 0;
861 
862 	if(ct && ct->flags & APC_EXTENSIBLE) {
863 		value = per_get_few_bits(pd, 1);
864 		if(value < 0) ASN__DECODE_STARVED;
865 		if(value) ct = 0;	/* Not restricted */
866 	}
867 
868 	if(ct && ct->range_bits >= 0) {
869 		value = per_get_few_bits(pd, ct->range_bits);
870 		if(value < 0) ASN__DECODE_STARVED;
871 		ASN_DEBUG("CHOICE %s got index %d in range %d",
872 			td->name, value, ct->range_bits);
873 		if(value > ct->upper_bound)
874 			ASN__DECODE_FAILED;
875 	} else {
876 		if(specs->ext_start == -1)
877 			ASN__DECODE_FAILED;
878 		value = uper_get_nsnnwn(pd);
879 		if(value < 0) ASN__DECODE_STARVED;
880 		value += specs->ext_start;
881 		if((unsigned)value >= td->elements_count)
882 			ASN__DECODE_FAILED;
883 	}
884 
885 	/* Adjust if canonical order is different from natural order */
886 	if(specs->from_canonical_order) {
887         ASN_DEBUG("CHOICE presence from wire %d", value);
888 		value = specs->from_canonical_order[value];
889         ASN_DEBUG("CHOICE presence index effective %d", value);
890     }
891 
892 	/* Set presence to be able to free it later */
893 	_set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
894 
895 	elm = &td->elements[value];
896 	if(elm->flags & ATF_POINTER) {
897 		/* Member is a pointer to another structure */
898 		memb_ptr2 = (void **)((char *)st + elm->memb_offset);
899 	} else {
900 		memb_ptr = (char *)st + elm->memb_offset;
901 		memb_ptr2 = &memb_ptr;
902 	}
903 	ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
904 
905 	if(ct && ct->range_bits >= 0) {
906 		rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
907 			elm->encoding_constraints.per_constraints, memb_ptr2, pd);
908 	} else {
909 		rv = uper_open_type_get(opt_codec_ctx, elm->type,
910 			elm->encoding_constraints.per_constraints, memb_ptr2, pd);
911 	}
912 
913 	if(rv.code != RC_OK)
914 		ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
915 			elm->name, td->name, rv.code);
916 	return rv;
917 }
918 
919 asn_enc_rval_t
CHOICE_encode_uper(const asn_TYPE_descriptor_t * td,const asn_per_constraints_t * constraints,const void * sptr,asn_per_outp_t * po)920 CHOICE_encode_uper(const asn_TYPE_descriptor_t *td,
921                    const asn_per_constraints_t *constraints, const void *sptr,
922                    asn_per_outp_t *po) {
923     const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
924 	asn_TYPE_member_t *elm;	/* CHOICE's element */
925 	const asn_per_constraint_t *ct;
926 	const void *memb_ptr;
927 	unsigned present;
928 	int present_enc;
929 
930 	if(!sptr) ASN__ENCODE_FAILED;
931 
932 	ASN_DEBUG("Encoding %s as CHOICE", td->name);
933 
934 	if(constraints) ct = &constraints->value;
935 	else if(td->encoding_constraints.per_constraints)
936 		ct = &td->encoding_constraints.per_constraints->value;
937 	else ct = 0;
938 
939 	present = _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
940 
941 	/*
942 	 * If the structure was not initialized properly, it cannot be encoded:
943 	 * can't deduce what to encode in the choice type.
944 	 */
945 	if(present == 0 || present > td->elements_count)
946 		ASN__ENCODE_FAILED;
947 	else
948 		present--;
949 
950 	ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
951 
952     /* Adjust if canonical order is different from natural order */
953     if(specs->to_canonical_order)
954         present_enc = specs->to_canonical_order[present];
955     else
956         present_enc = present;
957 
958     if(ct && ct->range_bits >= 0) {
959 		if(present_enc < ct->lower_bound
960 		|| present_enc > ct->upper_bound) {
961 			if(ct->flags & APC_EXTENSIBLE) {
962                 ASN_DEBUG(
963                     "CHOICE member %d (enc %d) is an extension (%ld..%ld)",
964                     present, present_enc, ct->lower_bound, ct->upper_bound);
965                 if(per_put_few_bits(po, 1, 1))
966 					ASN__ENCODE_FAILED;
967 			} else {
968 				ASN__ENCODE_FAILED;
969 			}
970 			ct = 0;
971 		}
972 	}
973 	if(ct && ct->flags & APC_EXTENSIBLE) {
974         ASN_DEBUG("CHOICE member %d (enc %d) is not an extension (%ld..%ld)",
975                   present, present_enc, ct->lower_bound, ct->upper_bound);
976         if(per_put_few_bits(po, 0, 1))
977 			ASN__ENCODE_FAILED;
978     }
979 
980 
981 	elm = &td->elements[present];
982     ASN_DEBUG("CHOICE member \"%s\" %d (as %d)", elm->name, present,
983               present_enc);
984     if(elm->flags & ATF_POINTER) {
985 		/* Member is a pointer to another structure */
986         memb_ptr =
987             *(const void *const *)((const char *)sptr + elm->memb_offset);
988         if(!memb_ptr) ASN__ENCODE_FAILED;
989 	} else {
990         memb_ptr = (const char *)sptr + elm->memb_offset;
991     }
992 
993     if(ct && ct->range_bits >= 0) {
994         if(per_put_few_bits(po, present_enc, ct->range_bits))
995             ASN__ENCODE_FAILED;
996 
997         return elm->type->op->uper_encoder(
998             elm->type, elm->encoding_constraints.per_constraints, memb_ptr, po);
999     } else {
1000         asn_enc_rval_t rval;
1001         if(specs->ext_start == -1) ASN__ENCODE_FAILED;
1002         if(uper_put_nsnnwn(po, present_enc - specs->ext_start))
1003             ASN__ENCODE_FAILED;
1004         if(uper_open_type_put(elm->type,
1005                               elm->encoding_constraints.per_constraints,
1006                               memb_ptr, po))
1007             ASN__ENCODE_FAILED;
1008         rval.encoded = 0;
1009         ASN__ENCODED_OK(rval);
1010     }
1011 }
1012 
1013 
1014 int
CHOICE_print(const asn_TYPE_descriptor_t * td,const void * sptr,int ilevel,asn_app_consume_bytes_f * cb,void * app_key)1015 CHOICE_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
1016              asn_app_consume_bytes_f *cb, void *app_key) {
1017     const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
1018 	unsigned present;
1019 
1020 	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
1021 
1022 	/*
1023 	 * Figure out which CHOICE element is encoded.
1024 	 */
1025 	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
1026 
1027 	/*
1028 	 * Print that element.
1029 	 */
1030 	if(present > 0 && present <= td->elements_count) {
1031 		asn_TYPE_member_t *elm = &td->elements[present-1];
1032 		const void *memb_ptr;
1033 
1034 		if(elm->flags & ATF_POINTER) {
1035 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
1036 			if(!memb_ptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
1037 		} else {
1038 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
1039 		}
1040 
1041 		/* Print member's name and stuff */
1042 		if(0) {
1043 			if(cb(elm->name, strlen(elm->name), app_key) < 0
1044 			|| cb(": ", 2, app_key) < 0)
1045 				return -1;
1046 		}
1047 
1048 		return elm->type->op->print_struct(elm->type, memb_ptr, ilevel,
1049 			cb, app_key);
1050 	} else {
1051 		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
1052 	}
1053 }
1054 
1055 void
CHOICE_free(const asn_TYPE_descriptor_t * td,void * ptr,enum asn_struct_free_method method)1056 CHOICE_free(const asn_TYPE_descriptor_t *td, void *ptr,
1057             enum asn_struct_free_method method) {
1058     const asn_CHOICE_specifics_t *specs =
1059         (const asn_CHOICE_specifics_t *)td->specifics;
1060     unsigned present;
1061 
1062 	if(!td || !ptr)
1063 		return;
1064 
1065 	ASN_DEBUG("Freeing %s as CHOICE", td->name);
1066 
1067 	/*
1068 	 * Figure out which CHOICE element is encoded.
1069 	 */
1070 	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
1071 
1072 	/*
1073 	 * Free that element.
1074 	 */
1075 	if(present > 0 && present <= td->elements_count) {
1076 		asn_TYPE_member_t *elm = &td->elements[present-1];
1077 		void *memb_ptr;
1078 
1079 		if(elm->flags & ATF_POINTER) {
1080 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
1081 			if(memb_ptr)
1082 				ASN_STRUCT_FREE(*elm->type, memb_ptr);
1083 		} else {
1084 			memb_ptr = (void *)((char *)ptr + elm->memb_offset);
1085 			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
1086 		}
1087 	}
1088 
1089     switch(method) {
1090     case ASFM_FREE_EVERYTHING:
1091         FREEMEM(ptr);
1092         break;
1093     case ASFM_FREE_UNDERLYING:
1094         break;
1095     case ASFM_FREE_UNDERLYING_AND_RESET:
1096         memset(ptr, 0, specs->struct_size);
1097         break;
1098     }
1099 }
1100 
1101 
1102 /*
1103  * The following functions functions offer protection against -fshort-enums,
1104  * compatible with little- and big-endian machines.
1105  * If assertion is triggered, either disable -fshort-enums, or add an entry
1106  * here with the ->pres_size of your target stracture.
1107  * Unless the target structure is packed, the ".present" member
1108  * is guaranteed to be aligned properly. ASN.1 compiler itself does not
1109  * produce packed code.
1110  */
1111 static unsigned
_fetch_present_idx(const void * struct_ptr,unsigned pres_offset,unsigned pres_size)1112 _fetch_present_idx(const void *struct_ptr, unsigned pres_offset,
1113                    unsigned pres_size) {
1114     const void *present_ptr;
1115 	unsigned present;
1116 
1117 	present_ptr = ((const char *)struct_ptr) + pres_offset;
1118 
1119 	switch(pres_size) {
1120 	case sizeof(int):	present = *(const unsigned int *)present_ptr; break;
1121 	case sizeof(short):	present = *(const unsigned short *)present_ptr; break;
1122 	case sizeof(char):	present = *(const unsigned char *)present_ptr; break;
1123 	default:
1124 		/* ANSI C mandates enum to be equivalent to integer */
1125 		assert(pres_size != sizeof(int));
1126 		return 0;	/* If not aborted, pass back safe value */
1127 	}
1128 
1129 	return present;
1130 }
1131 
1132 static void
_set_present_idx(void * struct_ptr,unsigned pres_offset,unsigned pres_size,unsigned present)1133 _set_present_idx(void *struct_ptr, unsigned pres_offset, unsigned pres_size,
1134                  unsigned present) {
1135     void *present_ptr;
1136 	present_ptr = ((char *)struct_ptr) + pres_offset;
1137 
1138 	switch(pres_size) {
1139 	case sizeof(int):	*(unsigned int *)present_ptr   = present; break;
1140 	case sizeof(short):	*(unsigned short *)present_ptr = present; break;
1141 	case sizeof(char):	*(unsigned char *)present_ptr  = present; break;
1142 	default:
1143 		/* ANSI C mandates enum to be equivalent to integer */
1144 		assert(pres_size != sizeof(int));
1145 	}
1146 }
1147 
1148 static const void *
_get_member_ptr(const asn_TYPE_descriptor_t * td,const void * sptr,asn_TYPE_member_t ** elm_ptr,unsigned * present_out)1149 _get_member_ptr(const asn_TYPE_descriptor_t *td, const void *sptr,
1150                 asn_TYPE_member_t **elm_ptr, unsigned *present_out) {
1151     const asn_CHOICE_specifics_t *specs =
1152         (const asn_CHOICE_specifics_t *)td->specifics;
1153     unsigned present;
1154 
1155     if(!sptr) {
1156         *elm_ptr = NULL;
1157         *present_out = 0;
1158         return NULL;
1159     }
1160 
1161     /*
1162 	 * Figure out which CHOICE element is encoded.
1163 	 */
1164 	present = _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
1165     *present_out = present;
1166 
1167     /*
1168      * The presence index is intentionally 1-based to avoid
1169      * treating zeroed structure as a valid one.
1170      */
1171 	if(present > 0 && present <= td->elements_count) {
1172         asn_TYPE_member_t *const elm = &td->elements[present - 1];
1173         const void *memb_ptr;
1174 
1175 		if(elm->flags & ATF_POINTER) {
1176             memb_ptr =
1177                 *(const void *const *)((const char *)sptr + elm->memb_offset);
1178         } else {
1179             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
1180         }
1181         *elm_ptr = elm;
1182         return memb_ptr;
1183     } else {
1184         *elm_ptr = NULL;
1185         return NULL;
1186     }
1187 
1188 }
1189 
1190 int
CHOICE_compare(const asn_TYPE_descriptor_t * td,const void * aptr,const void * bptr)1191 CHOICE_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) {
1192     asn_TYPE_member_t *aelm;
1193     asn_TYPE_member_t *belm;
1194     unsigned apresent = 0;
1195     unsigned bpresent = 0;
1196     const void *amember = _get_member_ptr(td, aptr, &aelm, &apresent);
1197     const void *bmember = _get_member_ptr(td, bptr, &belm, &bpresent);
1198 
1199     if(amember && bmember) {
1200         if(apresent == bpresent) {
1201             assert(aelm == belm);
1202             return aelm->type->op->compare_struct(aelm->type, amember, bmember);
1203         } else if(apresent < bpresent) {
1204             return -1;
1205         } else {
1206             return 1;
1207         }
1208     } else if(!amember) {
1209         return -1;
1210     } else {
1211         return 1;
1212     }
1213 }
1214 
1215 /*
1216  * Return the 1-based choice variant presence index.
1217  * Returns 0 in case of error.
1218  */
1219 unsigned
CHOICE_variant_get_presence(const asn_TYPE_descriptor_t * td,const void * sptr)1220 CHOICE_variant_get_presence(const asn_TYPE_descriptor_t *td, const void *sptr) {
1221     const asn_CHOICE_specifics_t *specs =
1222         (const asn_CHOICE_specifics_t *)td->specifics;
1223     return _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
1224 }
1225 
1226 /*
1227  * Sets or resets the 1-based choice variant presence index.
1228  * In case a previous index is not zero, the currently selected structure
1229  * member is freed and zeroed-out first.
1230  * Returns 0 on success and -1 on error.
1231  */
1232 int
CHOICE_variant_set_presence(const asn_TYPE_descriptor_t * td,void * sptr,unsigned present)1233 CHOICE_variant_set_presence(const asn_TYPE_descriptor_t *td, void *sptr,
1234                             unsigned present) {
1235     const asn_CHOICE_specifics_t *specs =
1236         (const asn_CHOICE_specifics_t *)td->specifics;
1237     unsigned old_present;
1238 
1239     if(!sptr) {
1240         return -1;
1241     }
1242 
1243     if(present > td->elements_count)
1244         return -1;
1245 
1246     old_present =
1247         _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
1248     if(present == old_present)
1249         return 0;
1250 
1251     if(old_present != 0) {
1252         assert(old_present <= td->elements_count);
1253         ASN_STRUCT_RESET(*td, sptr);
1254     }
1255 
1256     _set_present_idx(sptr, specs->pres_offset, specs->pres_size, present);
1257 
1258     return 0;
1259 }
1260 
1261 
1262 asn_random_fill_result_t
CHOICE_random_fill(const asn_TYPE_descriptor_t * td,void ** sptr,const asn_encoding_constraints_t * constr,size_t max_length)1263 CHOICE_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
1264                    const asn_encoding_constraints_t *constr,
1265                    size_t max_length) {
1266     const asn_CHOICE_specifics_t *specs =
1267         (const asn_CHOICE_specifics_t *)td->specifics;
1268     asn_random_fill_result_t res;
1269     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
1270     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
1271     const asn_TYPE_member_t *elm;
1272     unsigned present;
1273     void *memb_ptr;   /* Pointer to the member */
1274     void **memb_ptr2; /* Pointer to that pointer */
1275     void *st = *sptr;
1276 
1277     if(max_length == 0) return result_skipped;
1278 
1279     (void)constr;
1280 
1281     if(st == NULL) {
1282         st = CALLOC(1, specs->struct_size);
1283         if(st == NULL) {
1284             return result_failed;
1285         }
1286     }
1287 
1288     present = asn_random_between(1, td->elements_count);
1289     elm = &td->elements[present - 1];
1290 
1291 	if(elm->flags & ATF_POINTER) {
1292 		/* Member is a pointer to another structure */
1293 		memb_ptr2 = (void **)((char *)st + elm->memb_offset);
1294 	} else {
1295 		memb_ptr = (char *)st + elm->memb_offset;
1296 		memb_ptr2 = &memb_ptr;
1297 	}
1298 
1299     res = elm->type->op->random_fill(elm->type, memb_ptr2,
1300                                     &elm->encoding_constraints, max_length);
1301     _set_present_idx(st, specs->pres_offset, specs->pres_size, present);
1302     if(res.code == ARFILL_OK) {
1303         *sptr = st;
1304     } else {
1305         if(st == *sptr) {
1306             ASN_STRUCT_RESET(*td, st);
1307         } else {
1308             ASN_STRUCT_FREE(*td, st);
1309         }
1310     }
1311 
1312     return res;
1313 }
1314 
1315 
1316 asn_TYPE_operation_t asn_OP_CHOICE = {
1317 	CHOICE_free,
1318 	CHOICE_print,
1319 	CHOICE_compare,
1320 	CHOICE_decode_ber,
1321 	CHOICE_encode_der,
1322 	CHOICE_decode_xer,
1323 	CHOICE_encode_xer,
1324 #ifdef	ASN_DISABLE_OER_SUPPORT
1325 	0,
1326 	0,
1327 #else
1328 	CHOICE_decode_oer,
1329 	CHOICE_encode_oer,
1330 #endif  /* ASN_DISABLE_OER_SUPPORT */
1331 #ifdef ASN_DISABLE_PER_SUPPORT
1332 	0,
1333 	0,
1334 #else
1335 	CHOICE_decode_uper,
1336 	CHOICE_encode_uper,
1337 #endif	/* ASN_DISABLE_PER_SUPPORT */
1338 	CHOICE_random_fill,
1339 	CHOICE_outmost_tag
1340 };
1341