1 /*-
2  * Copyright (c) 2003, 2004, 2005, 2006 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.h>
8 
9 /* Check that all the mandatory members are present */
10 static int _SET_is_populated(asn_TYPE_descriptor_t *td, void *st);
11 
12 /*
13  * Number of bytes left for this structure.
14  * (ctx->left) indicates the number of bytes _transferred_ for the structure.
15  * (size) contains the number of bytes in the buffer passed.
16  */
17 #define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
18 
19 /*
20  * If the subprocessor function returns with an indication that it wants
21  * more data, it may well be a fatal decoding problem, because the
22  * size is constrained by the <TLV>'s L, even if the buffer size allows
23  * reading more data.
24  * For example, consider the buffer containing the following TLVs:
25  * <T:5><L:1><V> <T:6>...
26  * The TLV length clearly indicates that one byte is expected in V, but
27  * if the V processor returns with "want more data" even if the buffer
28  * contains way more data than the V processor have seen.
29  */
30 #define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
31 
32 /*
33  * This macro "eats" the part of the buffer which is definitely "consumed",
34  * i.e. was correctly converted into local representation or rightfully skipped.
35  */
36 #undef	ADVANCE
37 #define	ADVANCE(num_bytes)	do {		\
38 		size_t num = num_bytes;		\
39 		ptr = ((const char *)ptr) + num;\
40 		size -= num;			\
41 		if(ctx->left >= 0)		\
42 			ctx->left -= num;	\
43 		consumed_myself += num;		\
44 	} while(0)
45 
46 /*
47  * Switch to the next phase of parsing.
48  */
49 #undef	NEXT_PHASE
50 #define	NEXT_PHASE(ctx)	do {			\
51 		ctx->phase++;			\
52 		ctx->step = 0;			\
53 	} 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  * Tags are canonically sorted in the tag2element map.
67  */
68 static int
_t2e_cmp(const void * ap,const void * bp)69 _t2e_cmp(const void *ap, const void *bp) {
70 	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
71 	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
72 
73 	int a_class = BER_TAG_CLASS(a->el_tag);
74 	int b_class = BER_TAG_CLASS(b->el_tag);
75 
76 	if(a_class == b_class) {
77 		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
78 		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
79 
80 		if(a_value == b_value)
81 			return 0;
82 		else if(a_value < b_value)
83 			return -1;
84 		else
85 			return 1;
86 	} else if(a_class < b_class) {
87 		return -1;
88 	} else {
89 		return 1;
90 	}
91 }
92 
93 /*
94  * The decoder of the SET type.
95  */
96 asn_dec_rval_t
SET_decode_ber(asn_codec_ctx_t * opt_codec_ctx,asn_TYPE_descriptor_t * td,void ** struct_ptr,const void * ptr,size_t size,int tag_mode)97 SET_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
98 	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
99 	/*
100 	 * Bring closer parts of structure description.
101 	 */
102 	asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
103 	asn_TYPE_member_t *elements = td->elements;
104 
105 	/*
106 	 * Parts of the structure being constructed.
107 	 */
108 	void *st = *struct_ptr;	/* Target structure. */
109 	asn_struct_ctx_t *ctx;	/* Decoder context */
110 
111 	ber_tlv_tag_t tlv_tag;	/* T from TLV */
112 	asn_dec_rval_t rval;	/* Return code from subparsers */
113 
114 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
115 	int edx;			/* SET element's index */
116 
117 	ASN_DEBUG("Decoding %s as SET", td->name);
118 
119 	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
120 		_ASN_DECODE_FAILED;
121 
122 	/*
123 	 * Create the target structure if it is not present already.
124 	 */
125 	if(st == 0) {
126 		st = *struct_ptr = CALLOC(1, specs->struct_size);
127 		if(st == 0) {
128 			RETURN(RC_FAIL);
129 		}
130 	}
131 
132 	/*
133 	 * Restore parsing context.
134 	 */
135 	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
136 
137 	/*
138 	 * Start to parse where left previously
139 	 */
140 	switch(ctx->phase) {
141 	case 0:
142 		/*
143 		 * PHASE 0.
144 		 * Check that the set of tags associated with given structure
145 		 * perfectly fits our expectations.
146 		 */
147 
148 		rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
149 			tag_mode, 1, &ctx->left, 0);
150 		if(rval.code != RC_OK) {
151 			ASN_DEBUG("%s tagging check failed: %d",
152 				td->name, rval.code);
153 			return rval;
154 		}
155 
156 		if(ctx->left >= 0)
157 			ctx->left += rval.consumed; /* ?Substracted below! */
158 		ADVANCE(rval.consumed);
159 
160 		NEXT_PHASE(ctx);
161 
162 		ASN_DEBUG("Structure advertised %ld bytes, "
163 			"buffer contains %ld", (long)ctx->left, (long)size);
164 
165 		/* Fall through */
166 	case 1:
167 		/*
168 		 * PHASE 1.
169 		 * From the place where we've left it previously,
170 		 * try to decode the next member from the list of
171 		 * this structure's elements.
172 		 * Note that elements in BER may arrive out of
173 		 * order, yet DER mandates that they shall arive in the
174 		 * canonical order of their tags. So, there is a room
175 		 * for optimization.
176 		 */
177 	  for(;; ctx->step = 0) {
178 		asn_TYPE_tag2member_t *t2m;
179 		asn_TYPE_tag2member_t key;
180 		void *memb_ptr;		/* Pointer to the member */
181 		void **memb_ptr2;	/* Pointer to that pointer */
182 		ssize_t tag_len;	/* Length of TLV's T */
183 
184 		if(ctx->step & 1) {
185 			edx = ctx->step >> 1;
186 			goto microphase2;
187 		}
188 
189 		/*
190 		 * MICROPHASE 1: Synchronize decoding.
191 		 */
192 
193 		if(ctx->left == 0)
194 			/*
195 			 * No more things to decode.
196 			 * Exit out of here and check whether all mandatory
197 			 * elements have been received (in the next phase).
198 			 */
199 			break;
200 
201 		/*
202 		 * Fetch the T from TLV.
203 		 */
204 		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
205 		switch(tag_len) {
206 		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
207 			/* Fall through */
208 		case -1: RETURN(RC_FAIL);
209 		}
210 
211 		if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
212 			if(LEFT < 2) {
213 				if(SIZE_VIOLATION)
214 					RETURN(RC_FAIL);
215 				else
216 					RETURN(RC_WMORE);
217 			} else if(((const uint8_t *)ptr)[1] == 0) {
218 				/*
219 				 * Found the terminator of the
220 				 * indefinite length structure.
221 				 * Invoke the generic finalization function.
222 				 */
223 				goto phase3;
224 			}
225 		}
226 
227 		key.el_tag = tlv_tag;
228 		t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
229 				specs->tag2el, specs->tag2el_count,
230 				sizeof(specs->tag2el[0]), _t2e_cmp);
231 		if(t2m) {
232 			/*
233 			 * Found the element corresponding to the tag.
234 			 */
235 			edx = t2m->el_no;
236 			ctx->step = (edx << 1) + 1;
237 			ASN_DEBUG("Got tag %s (%s), edx %d",
238 				ber_tlv_tag_string(tlv_tag), td->name, edx);
239 		} else if(specs->extensible == 0) {
240 			ASN_DEBUG("Unexpected tag %s "
241 				"in non-extensible SET %s",
242 				ber_tlv_tag_string(tlv_tag), td->name);
243 			RETURN(RC_FAIL);
244 		} else {
245 			/* Skip this tag */
246 			ssize_t skip;
247 
248 			ASN_DEBUG("Skipping unknown tag %s",
249 				ber_tlv_tag_string(tlv_tag));
250 
251 			skip = ber_skip_length(opt_codec_ctx,
252 				BER_TLV_CONSTRUCTED(ptr),
253 				(const char *)ptr + tag_len, LEFT - tag_len);
254 
255 			switch(skip) {
256 			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
257 				/* Fall through */
258 			case -1: RETURN(RC_FAIL);
259 			}
260 
261 			ADVANCE(skip + tag_len);
262 			continue;  /* Try again with the next tag */
263 		}
264 
265 		/*
266 		 * MICROPHASE 2: Invoke the member-specific decoder.
267 		 */
268 	microphase2:
269 
270 		/*
271 		 * Check for duplications: must not overwrite
272 		 * already decoded elements.
273 		 */
274 		if(ASN_SET_ISPRESENT2((char *)st + specs->pres_offset, edx)) {
275 			ASN_DEBUG("SET %s: Duplicate element %s (%d)",
276 				td->name, elements[edx].name, edx);
277 			RETURN(RC_FAIL);
278 		}
279 
280 		/*
281 		 * Compute the position of the member inside a structure,
282 		 * and also a type of containment (it may be contained
283 		 * as pointer or using inline inclusion).
284 		 */
285 		if(elements[edx].flags & ATF_POINTER) {
286 			/* Member is a pointer to another structure */
287 			memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
288 		} else {
289 			/*
290 			 * A pointer to a pointer
291 			 * holding the start of the structure
292 			 */
293 			memb_ptr = (char *)st + elements[edx].memb_offset;
294 			memb_ptr2 = &memb_ptr;
295 		}
296 		/*
297 		 * Invoke the member fetch routine according to member's type
298 		 */
299 		rval = elements[edx].type->ber_decoder(opt_codec_ctx,
300 				elements[edx].type,
301 				memb_ptr2, ptr, LEFT,
302 				elements[edx].tag_mode);
303 		switch(rval.code) {
304 		case RC_OK:
305 			ASN_SET_MKPRESENT((char *)st + specs->pres_offset, edx);
306 			break;
307 		case RC_WMORE: /* More data expected */
308 			if(!SIZE_VIOLATION) {
309 				ADVANCE(rval.consumed);
310 				RETURN(RC_WMORE);
311 			}
312 			/* Fail through */
313 		case RC_FAIL: /* Fatal error */
314 			RETURN(RC_FAIL);
315 		} /* switch(rval) */
316 
317 		ADVANCE(rval.consumed);
318 	  }	/* for(all structure members) */
319 
320 	phase3:
321 		ctx->phase = 3;
322 		/* Fall through */
323 	case 3:
324 	case 4:	/* Only 00 is expected */
325 		ASN_DEBUG("SET %s Leftover: %ld, size = %ld",
326 			td->name, (long)ctx->left, (long)size);
327 
328 		/*
329 		 * Skip everything until the end of the SET.
330 		 */
331 		while(ctx->left) {
332 			ssize_t tl, ll;
333 
334 			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
335 			switch(tl) {
336 			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
337 				/* Fall through */
338 			case -1: RETURN(RC_FAIL);
339 			}
340 
341 			/*
342 			 * If expected <0><0>...
343 			 */
344 			if(ctx->left < 0
345 				&& ((const uint8_t *)ptr)[0] == 0) {
346 				if(LEFT < 2) {
347 					if(SIZE_VIOLATION)
348 						RETURN(RC_FAIL);
349 					else
350 						RETURN(RC_WMORE);
351 				} else if(((const uint8_t *)ptr)[1] == 0) {
352 					/*
353 					 * Correctly finished with <0><0>.
354 					 */
355 					ADVANCE(2);
356 					ctx->left++;
357 					ctx->phase = 4;
358 					continue;
359 				}
360 			}
361 
362 			if(specs->extensible == 0 || ctx->phase == 4) {
363 				ASN_DEBUG("Unexpected continuation "
364 					"of a non-extensible type %s "
365 					"(ptr=%02x)",
366 					td->name, *(const uint8_t *)ptr);
367 				RETURN(RC_FAIL);
368 			}
369 
370 			ll = ber_skip_length(opt_codec_ctx,
371 				BER_TLV_CONSTRUCTED(ptr),
372 				(const char *)ptr + tl, LEFT - tl);
373 			switch(ll) {
374 			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
375 				/* Fall through */
376 			case -1: RETURN(RC_FAIL);
377 			}
378 
379 			ADVANCE(tl + ll);
380 		}
381 
382 		ctx->phase = 5;
383 	case 5:
384 		/* Check that all mandatory elements are present. */
385 		if(!_SET_is_populated(td, st))
386 			RETURN(RC_FAIL);
387 
388 		NEXT_PHASE(ctx);
389 	}
390 
391 	RETURN(RC_OK);
392 }
393 
394 static int
_SET_is_populated(asn_TYPE_descriptor_t * td,void * st)395 _SET_is_populated(asn_TYPE_descriptor_t *td, void *st) {
396 	asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
397 	int edx;
398 
399 	/*
400 	 * Check that all mandatory elements are present.
401 	 */
402 	for(edx = 0; edx < td->elements_count;
403 		edx += (8 * sizeof(specs->_mandatory_elements[0]))) {
404 		unsigned int midx, pres, must;
405 
406 		midx = edx/(8 * sizeof(specs->_mandatory_elements[0]));
407 		pres = ((unsigned int *)((char *)st + specs->pres_offset))[midx];
408 		must = sys_ntohl(specs->_mandatory_elements[midx]);
409 
410 		if((pres & must) == must) {
411 			/*
412 			 * Yes, everything seems to be in place.
413 			 */
414 		} else {
415 			ASN_DEBUG("One or more mandatory elements "
416 				"of a SET %s %d (%08x.%08x)=%08x "
417 				"are not present",
418 				td->name,
419 				midx,
420 				pres,
421 				must,
422 				(~(pres & must) & must)
423 			);
424 			return 0;
425 		}
426 	}
427 
428 	return 1;
429 }
430 
431 /*
432  * The DER encoder of the SET type.
433  */
434 asn_enc_rval_t
SET_encode_der(asn_TYPE_descriptor_t * td,void * sptr,int tag_mode,ber_tlv_tag_t tag,asn_app_consume_bytes_f * cb,void * app_key)435 SET_encode_der(asn_TYPE_descriptor_t *td,
436 	void *sptr, int tag_mode, ber_tlv_tag_t tag,
437 	asn_app_consume_bytes_f *cb, void *app_key) {
438 	asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
439 	size_t computed_size = 0;
440 	asn_enc_rval_t er;
441 	int t2m_build_own = (specs->tag2el_count != td->elements_count);
442 	asn_TYPE_tag2member_t *t2m;
443 	int t2m_count;
444 	ssize_t ret;
445 	int edx;
446 
447 	/*
448 	 * Use existing, or build our own tags map.
449 	 */
450 	if(t2m_build_own) {
451 		t2m = (asn_TYPE_tag2member_t *)alloca(
452 				td->elements_count * sizeof(t2m[0]));
453 		if(!t2m) _ASN_ENCODE_FAILED; /* There are such platforms */
454 		t2m_count = 0;
455 	} else {
456 		/*
457 		 * There is no untagged CHOICE in this SET.
458 		 * Employ existing table.
459 		 */
460 		t2m = specs->tag2el;
461 		t2m_count = specs->tag2el_count;
462 	}
463 
464 	/*
465 	 * Gather the length of the underlying members sequence.
466 	 */
467 	for(edx = 0; edx < td->elements_count; edx++) {
468 		asn_TYPE_member_t *elm = &td->elements[edx];
469 		asn_enc_rval_t tmper;
470 		void *memb_ptr;
471 
472 		/*
473 		 * Compute the length of the encoding of this member.
474 		 */
475 		if(elm->flags & ATF_POINTER) {
476 			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
477 			if(!memb_ptr) {
478 				if(!elm->optional)
479 					/* Mandatory elements missing */
480 					_ASN_ENCODE_FAILED;
481 				if(t2m_build_own) {
482 					t2m[t2m_count].el_no = edx;
483 					t2m[t2m_count].el_tag = 0;
484 					t2m_count++;
485 				}
486 				continue;
487 			}
488 		} else {
489 			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
490 		}
491 		tmper = elm->type->der_encoder(elm->type, memb_ptr,
492 			elm->tag_mode, elm->tag,
493 			0, 0);
494 		if(tmper.encoded == -1)
495 			return tmper;
496 		computed_size += tmper.encoded;
497 
498 		/*
499 		 * Remember the outmost tag of this member.
500 		 */
501 		if(t2m_build_own) {
502 			t2m[t2m_count].el_no = edx;
503 			t2m[t2m_count].el_tag = asn_TYPE_outmost_tag(
504 				elm->type, memb_ptr, elm->tag_mode, elm->tag);
505 			t2m_count++;
506 		} else {
507 			/*
508 			 * No dynamic sorting is necessary.
509 			 */
510 		}
511 	}
512 
513 	/*
514 	 * Finalize order of the components.
515 	 */
516 	assert(t2m_count == td->elements_count);
517 	if(t2m_build_own) {
518 		/*
519 		 * Sort the underlying members according to their
520 		 * canonical tags order. DER encoding mandates it.
521 		 */
522 		qsort(t2m, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
523 	} else {
524 		/*
525 		 * Tags are already sorted by the compiler.
526 		 */
527 	}
528 
529 	/*
530 	 * Encode the TLV for the sequence itself.
531 	 */
532 	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
533 	if(ret == -1) _ASN_ENCODE_FAILED;
534 	er.encoded = computed_size + ret;
535 
536 	if(!cb) _ASN_ENCODED_OK(er);
537 
538 	/*
539 	 * Encode all members.
540 	 */
541 	for(edx = 0; edx < td->elements_count; edx++) {
542 		asn_TYPE_member_t *elm;
543 		asn_enc_rval_t tmper;
544 		void *memb_ptr;
545 
546 		/* Encode according to the tag order */
547 		elm = &td->elements[t2m[edx].el_no];
548 
549 		if(elm->flags & ATF_POINTER) {
550 			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
551 			if(!memb_ptr) continue;
552 		} else {
553 			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
554 		}
555 		tmper = elm->type->der_encoder(elm->type, memb_ptr,
556 			elm->tag_mode, elm->tag,
557 			cb, app_key);
558 		if(tmper.encoded == -1)
559 			return tmper;
560 		computed_size -= tmper.encoded;
561 	}
562 
563 	if(computed_size != 0) {
564 		/*
565 		 * Encoded size is not equal to the computed size.
566 		 */
567 		_ASN_ENCODE_FAILED;
568 	}
569 
570 	_ASN_ENCODED_OK(er);
571 }
572 
573 #undef	XER_ADVANCE
574 #define	XER_ADVANCE(num_bytes)	do {			\
575 		size_t num = num_bytes;			\
576 		buf_ptr = ((const char *)buf_ptr) + num;\
577 		size -= num;				\
578 		consumed_myself += num;			\
579 	} while(0)
580 
581 /*
582  * Decode the XER (XML) data.
583  */
584 asn_dec_rval_t
SET_decode_xer(asn_codec_ctx_t * opt_codec_ctx,asn_TYPE_descriptor_t * td,void ** struct_ptr,const char * opt_mname,const void * buf_ptr,size_t size)585 SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
586 	void **struct_ptr, const char *opt_mname,
587 		const void *buf_ptr, size_t size) {
588 	/*
589 	 * Bring closer parts of structure description.
590 	 */
591 	asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
592 	asn_TYPE_member_t *elements = td->elements;
593 	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
594 
595 	/*
596 	 * ... and parts of the structure being constructed.
597 	 */
598 	void *st = *struct_ptr;	/* Target structure. */
599 	asn_struct_ctx_t *ctx;	/* Decoder context */
600 
601 	asn_dec_rval_t rval;		/* Return value from a decoder */
602 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
603 	int edx;			/* Element index */
604 
605 	/*
606 	 * Create the target structure if it is not present already.
607 	 */
608 	if(st == 0) {
609 		st = *struct_ptr = CALLOC(1, specs->struct_size);
610 		if(st == 0) RETURN(RC_FAIL);
611 	}
612 
613 	/*
614 	 * Restore parsing context.
615 	 */
616 	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
617 
618 	/*
619 	 * Phases of XER/XML processing:
620 	 * Phase 0: Check that the opening tag matches our expectations.
621 	 * Phase 1: Processing body and reacting on closing tag.
622 	 * Phase 2: Processing inner type.
623 	 * Phase 3: Skipping unknown extensions.
624 	 * Phase 4: PHASED OUT
625 	 */
626 	for(edx = ctx->step; ctx->phase <= 3;) {
627 		pxer_chunk_type_e ch_type;	/* XER chunk type */
628 		ssize_t ch_size;		/* Chunk size */
629 		xer_check_tag_e tcv;		/* Tag check value */
630 		asn_TYPE_member_t *elm;
631 
632 		/*
633 		 * Go inside the inner member of a set.
634 		 */
635 		if(ctx->phase == 2) {
636 			asn_dec_rval_t tmprval;
637 			void *memb_ptr;		/* Pointer to the member */
638 			void **memb_ptr2;	/* Pointer to that pointer */
639 
640 			if(ASN_SET_ISPRESENT2((char *)st + specs->pres_offset,
641 					edx)) {
642 				ASN_DEBUG("SET %s: Duplicate element %s (%d)",
643 				td->name, elements[edx].name, edx);
644 				RETURN(RC_FAIL);
645 			}
646 
647 			elm = &elements[edx];
648 
649 			if(elm->flags & ATF_POINTER) {
650 				/* Member is a pointer to another structure */
651 				memb_ptr2 = (void **)((char *)st + elm->memb_offset);
652 			} else {
653 				memb_ptr = (char *)st + elm->memb_offset;
654 				memb_ptr2 = &memb_ptr;
655 			}
656 
657 			/* Invoke the inner type decoder, m.b. multiple times */
658 			tmprval = elm->type->xer_decoder(opt_codec_ctx,
659 					elm->type, memb_ptr2, elm->name,
660 					buf_ptr, size);
661 			XER_ADVANCE(tmprval.consumed);
662 			if(tmprval.code != RC_OK)
663 				RETURN(tmprval.code);
664 			ctx->phase = 1;	/* Back to body processing */
665 			ASN_SET_MKPRESENT((char *)st + specs->pres_offset, edx);
666 			ASN_DEBUG("XER/SET phase => %d", ctx->phase);
667 			/* Fall through */
668 		}
669 
670 		/*
671 		 * Get the next part of the XML stream.
672 		 */
673 		ch_size = xer_next_token(&ctx->context,
674 			buf_ptr, size, &ch_type);
675 		switch(ch_size) {
676 		case -1: RETURN(RC_FAIL);
677 		case 0:  RETURN(RC_WMORE);
678 		default:
679 			switch(ch_type) {
680 			case PXER_COMMENT:	/* Got XML comment */
681 			case PXER_TEXT:		/* Ignore free-standing text */
682 				XER_ADVANCE(ch_size);	/* Skip silently */
683 				continue;
684 			case PXER_TAG:
685 				break;	/* Check the rest down there */
686 			}
687 		}
688 
689 		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
690 		ASN_DEBUG("XER/SET: tcv = %d, ph=%d", tcv, ctx->phase);
691 
692 		/* Skip the extensions section */
693 		if(ctx->phase == 3) {
694 			switch(xer_skip_unknown(tcv, &ctx->left)) {
695 			case -1:
696 				ctx->phase = 4;
697 				RETURN(RC_FAIL);
698 			case 1:
699 				ctx->phase = 1;
700 				/* Fall through */
701 			case 0:
702 				XER_ADVANCE(ch_size);
703 				continue;
704 			case 2:
705 				ctx->phase = 1;
706 				break;
707 			}
708 		}
709 
710 		switch(tcv) {
711 		case XCT_CLOSING:
712 			if(ctx->phase == 0) break;
713 			ctx->phase = 0;
714 			/* Fall through */
715 		case XCT_BOTH:
716 			if(ctx->phase == 0) {
717 				if(_SET_is_populated(td, st)) {
718 					XER_ADVANCE(ch_size);
719 					ctx->phase = 4;	/* Phase out */
720 					RETURN(RC_OK);
721 				} else {
722 					ASN_DEBUG("Premature end of XER SET");
723 					RETURN(RC_FAIL);
724 				}
725 			}
726 			/* Fall through */
727 		case XCT_OPENING:
728 			if(ctx->phase == 0) {
729 				XER_ADVANCE(ch_size);
730 				ctx->phase = 1;	/* Processing body phase */
731 				continue;
732 			}
733 			/* Fall through */
734 		case XCT_UNKNOWN_OP:
735 		case XCT_UNKNOWN_BO:
736 
737 			ASN_DEBUG("XER/SET: tcv=%d, ph=%d", tcv, ctx->phase);
738 			if(ctx->phase != 1)
739 				break;	/* Really unexpected */
740 
741 			/*
742 			 * Search which member corresponds to this tag.
743 			 */
744 			for(edx = 0; edx < td->elements_count; edx++) {
745 				switch(xer_check_tag(buf_ptr, ch_size,
746 					elements[edx].name)) {
747 				case XCT_BOTH:
748 				case XCT_OPENING:
749 					/*
750 					 * Process this member.
751 					 */
752 					ctx->step = edx;
753 					ctx->phase = 2;
754 					break;
755 				case XCT_UNKNOWN_OP:
756 				case XCT_UNKNOWN_BO:
757 					continue;
758 				default:
759 					edx = td->elements_count;
760 					break;	/* Phase out */
761 				}
762 				break;
763 			}
764 			if(edx != td->elements_count)
765 				continue;
766 
767 			/* It is expected extension */
768 			if(specs->extensible) {
769 				ASN_DEBUG("Got anticipated extension");
770 				/*
771 				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
772 				 * By using a mask. Only record a pure
773 				 * <opening> tags.
774 				 */
775 				if(tcv & XCT_CLOSING) {
776 					/* Found </extension> without body */
777 				} else {
778 					ctx->left = 1;
779 					ctx->phase = 3;	/* Skip ...'s */
780 				}
781 				XER_ADVANCE(ch_size);
782 				continue;
783 			}
784 
785 			/* Fall through */
786 		default:
787 			break;
788 		}
789 
790 		ASN_DEBUG("Unexpected XML tag in SET, expected \"%s\"",
791 			xml_tag);
792 		break;
793 	}
794 
795 	ctx->phase = 4;	/* "Phase out" on hard failure */
796 	RETURN(RC_FAIL);
797 }
798 
799 asn_enc_rval_t
SET_encode_xer(asn_TYPE_descriptor_t * td,void * sptr,int ilevel,enum xer_encoder_flags_e flags,asn_app_consume_bytes_f * cb,void * app_key)800 SET_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
801 	int ilevel, enum xer_encoder_flags_e flags,
802 		asn_app_consume_bytes_f *cb, void *app_key) {
803 	asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
804 	asn_enc_rval_t er;
805 	int xcan = (flags & XER_F_CANONICAL);
806 	asn_TYPE_tag2member_t *t2m = specs->tag2el_cxer;
807 	int t2m_count = specs->tag2el_cxer_count;
808 	int edx;
809 
810 	if(!sptr)
811 		_ASN_ENCODE_FAILED;
812 
813 	assert(t2m_count == td->elements_count);
814 
815 	er.encoded = 0;
816 
817 	for(edx = 0; edx < t2m_count; edx++) {
818 		asn_enc_rval_t tmper;
819 		asn_TYPE_member_t *elm;
820 		void *memb_ptr;
821 		const char *mname;
822 		unsigned int mlen;
823 
824 		elm = &td->elements[t2m[edx].el_no];
825 		mname = elm->name;
826 		mlen = strlen(elm->name);
827 
828 		if(elm->flags & ATF_POINTER) {
829 			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
830 			if(!memb_ptr) {
831 				if(elm->optional)
832 					continue;
833 				/* Mandatory element missing */
834 				_ASN_ENCODE_FAILED;
835 			}
836 		} else {
837 			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
838 		}
839 
840 		if(!xcan)
841 			_i_ASN_TEXT_INDENT(1, ilevel);
842 		_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
843 
844 		/* Print the member itself */
845 		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
846 				ilevel + 1, flags, cb, app_key);
847 		if(tmper.encoded == -1) return tmper;
848 
849 		_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
850 
851 		er.encoded += 5 + (2 * mlen) + tmper.encoded;
852 	}
853 
854 	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
855 
856 	_ASN_ENCODED_OK(er);
857 cb_failed:
858 	_ASN_ENCODE_FAILED;
859 }
860 
861 int
SET_print(asn_TYPE_descriptor_t * td,const void * sptr,int ilevel,asn_app_consume_bytes_f * cb,void * app_key)862 SET_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
863 		asn_app_consume_bytes_f *cb, void *app_key) {
864 	int edx;
865 	int ret;
866 
867 	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
868 
869 	/* Dump preamble */
870 	if(cb(td->name, strlen(td->name), app_key) < 0
871 	|| cb(" ::= {", 6, app_key) < 0)
872 		return -1;
873 
874 	for(edx = 0; edx < td->elements_count; edx++) {
875 		asn_TYPE_member_t *elm = &td->elements[edx];
876 		const void *memb_ptr;
877 
878 		if(elm->flags & ATF_POINTER) {
879 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
880 			if(!memb_ptr) {
881 				if(elm->optional) continue;
882 				/* Print <absent> line */
883 				/* Fall through */
884 			}
885 		} else {
886 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
887 		}
888 
889 		_i_INDENT(1);
890 
891 		/* Print the member's name and stuff */
892 		if(cb(elm->name, strlen(elm->name), app_key) < 0
893 		|| cb(": ", 2, app_key) < 0)
894 			return -1;
895 
896 		/* Print the member itself */
897 		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
898 			cb, app_key);
899 		if(ret) return ret;
900 	}
901 
902 	ilevel--;
903 	_i_INDENT(1);
904 
905 	return (cb("}", 1, app_key) < 0) ? -1 : 0;
906 }
907 
908 void
SET_free(asn_TYPE_descriptor_t * td,void * ptr,int contents_only)909 SET_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
910 	int edx;
911 
912 	if(!td || !ptr)
913 		return;
914 
915 	ASN_DEBUG("Freeing %s as SET", td->name);
916 
917 	for(edx = 0; edx < td->elements_count; edx++) {
918 		asn_TYPE_member_t *elm = &td->elements[edx];
919 		void *memb_ptr;
920 		if(elm->flags & ATF_POINTER) {
921 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
922 			if(memb_ptr)
923 				ASN_STRUCT_FREE(*elm->type, memb_ptr);
924 		} else {
925 			memb_ptr = (void *)((char *)ptr + elm->memb_offset);
926 			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
927 		}
928 	}
929 
930 	if(!contents_only) {
931 		FREEMEM(ptr);
932 	}
933 }
934 
935 int
SET_constraint(asn_TYPE_descriptor_t * td,const void * sptr,asn_app_constraint_failed_f * ctfailcb,void * app_key)936 SET_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
937 		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
938 	int edx;
939 
940 	if(!sptr) {
941 		_ASN_CTFAIL(app_key, td, sptr,
942 			"%s: value not given (%s:%d)",
943 			td->name, __FILE__, __LINE__);
944 		return -1;
945 	}
946 
947 	/*
948 	 * Iterate over structure members and check their validity.
949 	 */
950 	for(edx = 0; edx < td->elements_count; edx++) {
951 		asn_TYPE_member_t *elm = &td->elements[edx];
952 		const void *memb_ptr;
953 
954 		if(elm->flags & ATF_POINTER) {
955 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
956 			if(!memb_ptr) {
957 				if(elm->optional)
958 					continue;
959 				_ASN_CTFAIL(app_key, td, sptr,
960 				"%s: mandatory element %s absent (%s:%d)",
961 				td->name, elm->name, __FILE__, __LINE__);
962 				return -1;
963 			}
964 		} else {
965 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
966 		}
967 
968 		if(elm->memb_constraints) {
969 			int ret = elm->memb_constraints(elm->type, memb_ptr,
970 				ctfailcb, app_key);
971 			if(ret) return ret;
972 		} else {
973 			int ret = elm->type->check_constraints(elm->type,
974 				memb_ptr, ctfailcb, app_key);
975 			if(ret) return ret;
976 			/*
977 			 * Cannot inherit it earlier:
978 			 * need to make sure we get the updated version.
979 			 */
980 			elm->memb_constraints = elm->type->check_constraints;
981 		}
982 	}
983 
984 	return 0;
985 }
986