mirror of https://gerrit.osmocom.org/asn1c
fix after UPER round-trip fuzz
This commit is contained in:
parent
5de8274266
commit
836686167d
|
@ -415,8 +415,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc
|
|||
asn1p_expr_t *expr = arg->expr;
|
||||
asn1p_expr_t *v;
|
||||
int elements; /* Number of elements */
|
||||
int ext_start = -2;
|
||||
int ext_stop = -2;
|
||||
int first_extension = -1;
|
||||
tag2el_t *tag2el = NULL;
|
||||
int tag2el_count = 0;
|
||||
int tags_count;
|
||||
|
@ -456,9 +455,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc
|
|||
INDENTED(TQ_FOR(v, &(expr->members), next) {
|
||||
if(v->expr_type == A1TC_EXTENSIBLE) {
|
||||
if((++comp_mode) == 1)
|
||||
ext_start = elements - 1;
|
||||
else
|
||||
ext_stop = elements - 1;
|
||||
first_extension = elements;
|
||||
continue;
|
||||
}
|
||||
if(v->marker.flags & EM_OMITABLE)
|
||||
|
@ -546,10 +543,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc
|
|||
} else {
|
||||
OUT("0, 0, 0,\t/* Optional elements (not needed) */\n");
|
||||
}
|
||||
OUT("%d,\t/* Start extensions */\n",
|
||||
ext_start<0 ? -1 : ext_start);
|
||||
OUT("%d\t/* Stop extensions */\n",
|
||||
(ext_stop<ext_start)?elements+1:(ext_stop<0?-1:ext_stop));
|
||||
OUT("%d,\t/* First extension addition */\n", first_extension);
|
||||
INDENT(-1);
|
||||
OUT("};\n");
|
||||
|
||||
|
@ -1196,7 +1190,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
|
|||
OUT("asn_MAP_%s_from_canonical_%d,\n", MKID(expr),
|
||||
expr->_type_unique_index);
|
||||
} else { OUT("0, 0,\n"); }
|
||||
if(C99_MODE) OUT(".ext_start = ");
|
||||
if(C99_MODE) OUT(".first_extension = ");
|
||||
OUT("%d\t/* Extensions start */\n", compute_extensions_start(expr));
|
||||
);
|
||||
OUT("};\n");
|
||||
|
@ -3397,7 +3391,7 @@ compute_canonical_members_order(arg_t *arg, int el_count) {
|
|||
int *rmap;
|
||||
asn1p_expr_t *v;
|
||||
int eidx = 0;
|
||||
int ext_start = -1;
|
||||
int first_extension = -1;
|
||||
int nextmax = -1;
|
||||
int already_sorted = 1;
|
||||
|
||||
|
@ -3409,18 +3403,18 @@ compute_canonical_members_order(arg_t *arg, int el_count) {
|
|||
cmap[eidx].eidx = eidx;
|
||||
cmap[eidx].expr = v;
|
||||
eidx++;
|
||||
} else if(ext_start == -1)
|
||||
ext_start = eidx;
|
||||
} else if(first_extension == -1)
|
||||
first_extension = eidx;
|
||||
}
|
||||
|
||||
cameo_arg = arg;
|
||||
if(ext_start == -1) {
|
||||
if(first_extension == -1) {
|
||||
/* Sort the whole thing */
|
||||
qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
|
||||
} else {
|
||||
/* Sort root and extensions independently */
|
||||
qsort(cmap, ext_start, sizeof(*cmap), compar_cameo);
|
||||
qsort(cmap + ext_start, el_count - ext_start,
|
||||
qsort(cmap, first_extension, sizeof(*cmap), compar_cameo);
|
||||
qsort(cmap + first_extension, el_count - first_extension,
|
||||
sizeof(*cmap), compar_cameo);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*-
|
||||
/*
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
|
@ -66,10 +66,9 @@
|
|||
/*
|
||||
* Check whether we are inside the extensions group.
|
||||
*/
|
||||
#define IN_EXTENSION_GROUP(specs, memb_idx) \
|
||||
( (((signed)(memb_idx)) > (specs)->ext_after) \
|
||||
&&(((signed)(memb_idx)) < (specs)->ext_before))
|
||||
|
||||
#define IN_EXTENSION_GROUP(specs, memb_idx) \
|
||||
((specs)->first_extension >= 0 \
|
||||
&& (unsigned)(specs)->first_extension <= (memb_idx))
|
||||
|
||||
/*
|
||||
* Tags are canonically sorted in the tag2element map.
|
||||
|
@ -209,24 +208,19 @@ SEQUENCE_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
elements[edx].flags, elements[edx].optional,
|
||||
td->elements_count);
|
||||
|
||||
if(ctx->left == 0 /* No more stuff is expected */
|
||||
&& (
|
||||
/* Explicit OPTIONAL specification reaches the end */
|
||||
(edx + elements[edx].optional
|
||||
== td->elements_count)
|
||||
||
|
||||
/* All extensions are optional */
|
||||
(IN_EXTENSION_GROUP(specs, edx)
|
||||
&& specs->ext_before > (signed)td->elements_count)
|
||||
)
|
||||
) {
|
||||
ASN_DEBUG("End of SEQUENCE %s", td->name);
|
||||
/*
|
||||
* Found the legitimate end of the structure.
|
||||
*/
|
||||
PHASE_OUT(ctx);
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
if(ctx->left == 0 /* No more stuff is expected */
|
||||
&& (
|
||||
/* Explicit OPTIONAL specification reaches the end */
|
||||
(edx + elements[edx].optional == td->elements_count) ||
|
||||
/* All extensions are optional */
|
||||
IN_EXTENSION_GROUP(specs, edx))) {
|
||||
ASN_DEBUG("End of SEQUENCE %s", td->name);
|
||||
/*
|
||||
* Found the legitimate end of the structure.
|
||||
*/
|
||||
PHASE_OUT(ctx);
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch the T from TLV.
|
||||
|
@ -242,34 +236,31 @@ SEQUENCE_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
case -1: RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
|
||||
if(LEFT < 2) {
|
||||
if(SIZE_VIOLATION)
|
||||
RETURN(RC_FAIL);
|
||||
else
|
||||
RETURN(RC_WMORE);
|
||||
} else if(((const uint8_t *)ptr)[1] == 0) {
|
||||
ASN_DEBUG("edx = %zu, opt = %d, ec=%d",
|
||||
edx, elements[edx].optional,
|
||||
td->elements_count);
|
||||
if((edx + elements[edx].optional
|
||||
== td->elements_count)
|
||||
|| (IN_EXTENSION_GROUP(specs, edx)
|
||||
&& specs->ext_before
|
||||
> (signed)td->elements_count)) {
|
||||
/*
|
||||
* Yeah, baby! Found the terminator
|
||||
* of the indefinite length structure.
|
||||
*/
|
||||
/*
|
||||
* Proceed to the canonical
|
||||
* finalization function.
|
||||
* No advancing is necessary.
|
||||
*/
|
||||
goto phase3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
|
||||
if(LEFT < 2) {
|
||||
if(SIZE_VIOLATION) {
|
||||
RETURN(RC_FAIL);
|
||||
} else {
|
||||
RETURN(RC_WMORE);
|
||||
}
|
||||
} else if(((const uint8_t *)ptr)[1] == 0) {
|
||||
ASN_DEBUG("edx = %zu, opt = %d, ec=%d", edx,
|
||||
elements[edx].optional, td->elements_count);
|
||||
if((edx + elements[edx].optional == td->elements_count)
|
||||
|| IN_EXTENSION_GROUP(specs, edx)) {
|
||||
/*
|
||||
* Yeah, baby! Found the terminator
|
||||
* of the indefinite length structure.
|
||||
*/
|
||||
/*
|
||||
* Proceed to the canonical
|
||||
* finalization function.
|
||||
* No advancing is necessary.
|
||||
*/
|
||||
goto phase3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next available type with this tag.
|
||||
|
@ -766,19 +757,13 @@ SEQUENCE_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
ctx->phase = 0;
|
||||
/* Fall through */
|
||||
case XCT_BOTH:
|
||||
if(ctx->phase == 0) {
|
||||
if(edx >= td->elements_count
|
||||
||
|
||||
/* Explicit OPTIONAL specs reaches the end */
|
||||
(edx + elements[edx].optional
|
||||
== td->elements_count)
|
||||
||
|
||||
/* All extensions are optional */
|
||||
(IN_EXTENSION_GROUP(specs, edx)
|
||||
&& specs->ext_before
|
||||
> (signed)td->elements_count)
|
||||
) {
|
||||
XER_ADVANCE(ch_size);
|
||||
if(ctx->phase == 0) {
|
||||
if(edx >= td->elements_count ||
|
||||
/* Explicit OPTIONAL specs reaches the end */
|
||||
(edx + elements[edx].optional == td->elements_count) ||
|
||||
/* All extensions are optional */
|
||||
IN_EXTENSION_GROUP(specs, edx)) {
|
||||
XER_ADVANCE(ch_size);
|
||||
ctx->phase = 4; /* Phase out */
|
||||
RETURN(RC_OK);
|
||||
} else {
|
||||
|
@ -1113,11 +1098,11 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);
|
||||
|
||||
/* Handle extensions */
|
||||
if(specs->ext_before >= 0) {
|
||||
if(specs->first_extension < 0) {
|
||||
extpresent = 0;
|
||||
} else {
|
||||
extpresent = per_get_few_bits(pd, 1);
|
||||
if(extpresent < 0) ASN__DECODE_STARVED;
|
||||
} else {
|
||||
extpresent = 0;
|
||||
}
|
||||
|
||||
/* Prepare a place and read-in the presence bitmap */
|
||||
|
@ -1141,13 +1126,15 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
/*
|
||||
* Get the sequence ROOT elements.
|
||||
*/
|
||||
for(edx = 0; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
for(edx = 0;
|
||||
edx < (specs->first_extension < 0 ? td->elements_count
|
||||
: (size_t)specs->first_extension);
|
||||
edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
|
||||
if(IN_EXTENSION_GROUP(specs, edx))
|
||||
continue;
|
||||
assert(!IN_EXTENSION_GROUP(specs, edx));
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
|
@ -1210,7 +1197,7 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
bmlength = uper_get_nslength(pd);
|
||||
if(bmlength < 0) ASN__DECODE_STARVED;
|
||||
|
||||
ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name);
|
||||
ASN_DEBUG("Extensions %zd present in %s", bmlength, td->name);
|
||||
|
||||
epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
|
||||
if(!epres) ASN__DECODE_STARVED;
|
||||
|
@ -1228,38 +1215,35 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
td->name, (long)bmlength, *epres);
|
||||
|
||||
/* Go over extensions and read them in */
|
||||
for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
int present;
|
||||
for(edx = specs->first_extension; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
int present;
|
||||
|
||||
if(!IN_EXTENSION_GROUP(specs, edx)) {
|
||||
ASN_DEBUG("%zu is not an extension", edx);
|
||||
continue;
|
||||
}
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
|
||||
} else {
|
||||
memb_ptr = (void *)((char *)st + elm->memb_offset);
|
||||
memb_ptr2 = &memb_ptr;
|
||||
}
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
|
||||
} else {
|
||||
memb_ptr = (void *)((char *)st + elm->memb_offset);
|
||||
memb_ptr2 = &memb_ptr;
|
||||
}
|
||||
present = per_get_few_bits(&epmd, 1);
|
||||
if(present <= 0) {
|
||||
if(present < 0) break; /* No more extensions */
|
||||
continue;
|
||||
}
|
||||
|
||||
present = per_get_few_bits(&epmd, 1);
|
||||
if(present <= 0) {
|
||||
if(present < 0) break; /* No more extensions */
|
||||
continue;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
|
||||
rv = uper_open_type_get(opt_codec_ctx, elm->type,
|
||||
elm->encoding_constraints.per_constraints, memb_ptr2, pd);
|
||||
if(rv.code != RC_OK) {
|
||||
FREEMEM(epres);
|
||||
return rv;
|
||||
}
|
||||
ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name,
|
||||
*memb_ptr2);
|
||||
rv = uper_open_type_get(opt_codec_ctx, elm->type,
|
||||
elm->encoding_constraints.per_constraints,
|
||||
memb_ptr2, pd);
|
||||
if(rv.code != RC_OK) {
|
||||
FREEMEM(epres);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip over overflow extensions which aren't present
|
||||
|
@ -1274,6 +1258,8 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
FREEMEM(epres);
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
ASN_DEBUG("Skipped overflow extension");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1281,28 +1267,33 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
FREEMEM(epres);
|
||||
}
|
||||
|
||||
/* Fill DEFAULT members in extensions */
|
||||
for(edx = specs->roms_count; edx < specs->roms_count
|
||||
+ specs->aoms_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
void **memb_ptr2; /* Pointer to member pointer */
|
||||
if(specs->first_extension >= 0) {
|
||||
unsigned i;
|
||||
/* Fill DEFAULT members in extensions */
|
||||
for(i = specs->roms_count; i < specs->roms_count + specs->aoms_count;
|
||||
i++) {
|
||||
asn_TYPE_member_t *elm;
|
||||
void **memb_ptr2; /* Pointer to member pointer */
|
||||
|
||||
if(!elm->default_value_set) continue;
|
||||
edx = specs->oms[i];
|
||||
elm = &td->elements[edx];
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)st
|
||||
+ elm->memb_offset);
|
||||
if(*memb_ptr2) continue;
|
||||
} else {
|
||||
continue; /* Extensions are all optionals */
|
||||
}
|
||||
if(!elm->default_value_set) continue;
|
||||
|
||||
/* Set default value */
|
||||
if(elm->default_value_set(memb_ptr2)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
|
||||
if(*memb_ptr2) continue;
|
||||
} else {
|
||||
continue; /* Extensions are all optionals */
|
||||
}
|
||||
|
||||
/* Set default value */
|
||||
if(elm->default_value_set(memb_ptr2)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv.consumed = 0;
|
||||
rv.code = RC_OK;
|
||||
|
@ -1312,54 +1303,52 @@ SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
static int
|
||||
SEQUENCE__handle_extensions(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_per_outp_t *po1, asn_per_outp_t *po2) {
|
||||
const asn_SEQUENCE_specifics_t *specs
|
||||
= (const asn_SEQUENCE_specifics_t *)td->specifics;
|
||||
int exts_present = 0;
|
||||
int exts_count = 0;
|
||||
size_t edx;
|
||||
const asn_SEQUENCE_specifics_t *specs =
|
||||
(const asn_SEQUENCE_specifics_t *)td->specifics;
|
||||
int exts_present = 0;
|
||||
int exts_count = 0;
|
||||
size_t edx;
|
||||
|
||||
if(specs->ext_before < 0)
|
||||
return 0;
|
||||
if(specs->first_extension < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find out which extensions are present */
|
||||
for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
const void *memb_ptr; /* Pointer to the member */
|
||||
/* Find out which extensions are present */
|
||||
for(edx = specs->first_extension; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
const void *memb_ptr; /* Pointer to the member */
|
||||
const void *const *memb_ptr2; /* Pointer to that pointer */
|
||||
int present;
|
||||
|
||||
if(!IN_EXTENSION_GROUP(specs, edx)) {
|
||||
ASN_DEBUG("%s (@%zu) is not extension", elm->type->name, edx);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 =
|
||||
(const void *const *)((const char *)sptr + elm->memb_offset);
|
||||
present = (*memb_ptr2 != 0);
|
||||
} else {
|
||||
} else {
|
||||
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
|
||||
memb_ptr2 = &memb_ptr;
|
||||
present = 1;
|
||||
}
|
||||
|
||||
ASN_DEBUG("checking %s (@%zu) present => %d",
|
||||
elm->type->name, edx, present);
|
||||
exts_count++;
|
||||
exts_present += present;
|
||||
ASN_DEBUG("checking %s:%s (@%zu) present => %d", elm->name,
|
||||
elm->type->name, edx, present);
|
||||
exts_count++;
|
||||
exts_present += present;
|
||||
|
||||
/* Encode as presence marker */
|
||||
if(po1 && per_put_few_bits(po1, present, 1))
|
||||
return -1;
|
||||
/* Encode as open type field */
|
||||
if(po2 && present && uper_open_type_put(elm->type,
|
||||
elm->encoding_constraints.per_constraints, *memb_ptr2, po2))
|
||||
return -1;
|
||||
/* Encode as presence marker */
|
||||
if(po1 && per_put_few_bits(po1, present, 1)) {
|
||||
return -1;
|
||||
}
|
||||
/* Encode as open type field */
|
||||
if(po2 && present
|
||||
&& uper_open_type_put(elm->type,
|
||||
elm->encoding_constraints.per_constraints,
|
||||
*memb_ptr2, po2))
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return exts_present ? exts_count : 0;
|
||||
return exts_present ? exts_count : 0;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
|
@ -1382,20 +1371,19 @@ SEQUENCE_encode_uper(const asn_TYPE_descriptor_t *td,
|
|||
|
||||
ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
|
||||
|
||||
|
||||
/*
|
||||
* X.691#18.1 Whether structure is extensible
|
||||
* and whether to encode extensions
|
||||
*/
|
||||
if(specs->ext_before >= 0) {
|
||||
n_extensions = SEQUENCE__handle_extensions(td, sptr, 0, 0);
|
||||
if(n_extensions < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
if(per_put_few_bits(po, n_extensions ? 1 : 0, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
n_extensions = 0; /* There are no extensions to encode */
|
||||
}
|
||||
if(specs->first_extension < 0) {
|
||||
n_extensions = 0; /* There are no extensions to encode */
|
||||
} else {
|
||||
n_extensions = SEQUENCE__handle_extensions(td, sptr, 0, 0);
|
||||
if(n_extensions < 0) ASN__ENCODE_FAILED;
|
||||
if(per_put_few_bits(po, n_extensions ? 1 : 0, 1)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode a presence bitmap */
|
||||
for(i = 0; i < specs->roms_count; i++) {
|
||||
|
@ -1434,16 +1422,15 @@ SEQUENCE_encode_uper(const asn_TYPE_descriptor_t *td,
|
|||
/*
|
||||
* Encode the sequence ROOT elements.
|
||||
*/
|
||||
ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
|
||||
for(edx = 0; edx < ((specs->ext_after < 0)
|
||||
? td->elements_count : (size_t)specs->ext_before - 1); edx++) {
|
||||
|
||||
ASN_DEBUG("first_extension = %d, elements = %d", specs->first_extension,
|
||||
td->elements_count);
|
||||
for(edx = 0;
|
||||
edx < ((specs->first_extension < 0) ? td->elements_count
|
||||
: (size_t)specs->first_extension);
|
||||
edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
const void *memb_ptr; /* Pointer to the member */
|
||||
const void *const *memb_ptr2; /* Pointer to that pointer */
|
||||
|
||||
if(IN_EXTENSION_GROUP(specs, edx))
|
||||
continue;
|
||||
const void *memb_ptr; /* Pointer to the member */
|
||||
const void *const *memb_ptr2; /* Pointer to that pointer */
|
||||
|
||||
ASN_DEBUG("About to encode %s", elm->type->name);
|
||||
|
||||
|
@ -1468,17 +1455,17 @@ SEQUENCE_encode_uper(const asn_TYPE_descriptor_t *td,
|
|||
if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)
|
||||
continue;
|
||||
|
||||
ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
|
||||
er = elm->type->op->uper_encoder(elm->type, elm->encoding_constraints.per_constraints,
|
||||
*memb_ptr2, po);
|
||||
if(er.encoded == -1)
|
||||
return er;
|
||||
}
|
||||
ASN_DEBUG("Encoding %s->%s:%s", td->name, elm->name, elm->type->name);
|
||||
er = elm->type->op->uper_encoder(
|
||||
elm->type, elm->encoding_constraints.per_constraints, *memb_ptr2,
|
||||
po);
|
||||
if(er.encoded == -1) return er;
|
||||
}
|
||||
|
||||
/* No extensions to encode */
|
||||
if(!n_extensions) ASN__ENCODED_OK(er);
|
||||
|
||||
ASN_DEBUG("Length of %d bit-map", n_extensions);
|
||||
ASN_DEBUG("Length of extensions %d bit-map", n_extensions);
|
||||
/* #18.8. Write down the presence bit-map length. */
|
||||
if(uper_put_nslength(po, n_extensions))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
|
|
@ -34,9 +34,10 @@ typedef struct asn_SEQUENCE_specifics_s {
|
|||
|
||||
/*
|
||||
* Description of an extensions group.
|
||||
* Root components are clustered at the beginning of the structure,
|
||||
* whereas extensions are clustered at the end. -1 means not extensible.
|
||||
*/
|
||||
signed ext_after; /* Extensions start after this member */
|
||||
signed ext_before; /* Extensions stop before this member */
|
||||
signed first_extension; /* First extension addition */
|
||||
} asn_SEQUENCE_specifics_t;
|
||||
|
||||
|
||||
|
|
|
@ -37,9 +37,15 @@
|
|||
/*
|
||||
* Check whether we are inside the extensions group.
|
||||
*/
|
||||
#define IN_EXTENSION_GROUP(specs, memb_idx) \
|
||||
( (((ssize_t)(memb_idx)) > (specs)->ext_after) \
|
||||
&&(((ssize_t)(memb_idx)) < (specs)->ext_before))
|
||||
#define IN_EXTENSION_GROUP(specs, memb_idx) \
|
||||
((specs)->first_extension >= 0 \
|
||||
&& (unsigned)(specs)->first_extension <= (memb_idx))
|
||||
|
||||
#define IN_ROOT_GROUP_PRED(edx) \
|
||||
edx < (specs->first_extension < 0 ? td->elements_count \
|
||||
: (size_t)specs->first_extension)
|
||||
|
||||
#define FOR_IN_ROOT_GROUP(edx) for(edx = 0; IN_ROOT_GROUP_PRED(edx); edx++)
|
||||
|
||||
/*
|
||||
* Return a standardized complex structure.
|
||||
|
@ -117,7 +123,7 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
* Fetch preamble.
|
||||
*/
|
||||
asn_bit_data_t *preamble;
|
||||
int has_extensions_bit = (specs->ext_before >= 0);
|
||||
int has_extensions_bit = (specs->first_extension >= 0);
|
||||
size_t preamble_bits = (has_extensions_bit + specs->roms_count);
|
||||
size_t preamble_bytes = ((7 + preamble_bits) >> 3);
|
||||
|
||||
|
@ -146,26 +152,23 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
asn_bit_data_t *preamble = ctx->ptr;
|
||||
size_t edx;
|
||||
|
||||
ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
|
||||
ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1 (Root)", td->name);
|
||||
|
||||
assert(preamble);
|
||||
|
||||
for(edx = (ctx->step >> 1); edx < td->elements_count;
|
||||
for(edx = (ctx->step >> 1); IN_ROOT_GROUP_PRED(edx);
|
||||
edx++, ctx->step = (ctx->step & ~1) + 2) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
|
||||
ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
|
||||
|
||||
assert(!IN_EXTENSION_GROUP(specs, edx));
|
||||
|
||||
if(ctx->step & 1) {
|
||||
goto microphase2_decode_continues;
|
||||
}
|
||||
|
||||
|
||||
if(IN_EXTENSION_GROUP(specs, edx)) {
|
||||
/* Ignore non-root components in PHASE 1 */
|
||||
break;
|
||||
}
|
||||
|
||||
if(elm->optional) {
|
||||
int32_t present = asn_get_few_bits(preamble, 1);
|
||||
if(present < 0) {
|
||||
|
@ -229,7 +232,7 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
/* Cleanup preamble. */
|
||||
asn_bit_data_t *preamble = ctx->ptr;
|
||||
asn_bit_data_t *extadds;
|
||||
int has_extensions_bit = (specs->ext_before >= 0);
|
||||
int has_extensions_bit = (specs->first_extension >= 0);
|
||||
int extensions_present =
|
||||
has_extensions_bit
|
||||
&& (preamble->buffer == NULL
|
||||
|
@ -286,11 +289,13 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
ADVANCE(len);
|
||||
}
|
||||
NEXT_PHASE(ctx);
|
||||
ctx->step = (specs->ext_after + 1);
|
||||
ctx->step =
|
||||
(specs->first_extension < 0 ? td->elements_count
|
||||
: (size_t)specs->first_extension);
|
||||
/* Fall through */
|
||||
case 3:
|
||||
ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
|
||||
for(; ctx->step < specs->ext_before - 1; ctx->step++) {
|
||||
ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3 (Extensions)", td->name);
|
||||
for(; ctx->step < (signed)td->elements_count; ctx->step++) {
|
||||
asn_bit_data_t *extadds = ctx->ptr;
|
||||
size_t edx = ctx->step;
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
|
@ -378,7 +383,7 @@ SEQUENCE_encode_oer(const asn_TYPE_descriptor_t *td,
|
|||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;
|
||||
size_t computed_size = 0;
|
||||
int has_extensions_bit = (specs->ext_before >= 0);
|
||||
int has_extensions_bit = (specs->first_extension >= 0);
|
||||
size_t preamble_bits = (has_extensions_bit + specs->roms_count);
|
||||
uint32_t has_extensions = 0;
|
||||
size_t edx;
|
||||
|
@ -394,8 +399,7 @@ SEQUENCE_encode_oer(const asn_TYPE_descriptor_t *td,
|
|||
preamble.op_key = app_key;
|
||||
|
||||
if(has_extensions_bit) {
|
||||
for(edx = specs->ext_after + 1;
|
||||
(ssize_t)edx < specs->ext_before - 1; edx++) {
|
||||
for(edx = specs->first_extension; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
const void *memb_ptr = element_ptr(sptr, elm);
|
||||
if(memb_ptr) {
|
||||
|
@ -419,7 +423,7 @@ SEQUENCE_encode_oer(const asn_TYPE_descriptor_t *td,
|
|||
* Encode optional components bitmap.
|
||||
*/
|
||||
if(specs->roms_count) {
|
||||
for(edx = 0; edx < td->elements_count; edx++) {
|
||||
FOR_IN_ROOT_GROUP(edx) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
|
||||
if(IN_EXTENSION_GROUP(specs, edx)) break;
|
||||
|
@ -507,8 +511,7 @@ SEQUENCE_encode_oer(const asn_TYPE_descriptor_t *td,
|
|||
if(ret < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
/* Encode presence bitmap #16.4.3 */
|
||||
for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
|
||||
edx++) {
|
||||
for(edx = specs->first_extension; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
const void *memb_ptr = element_ptr(sptr, elm);
|
||||
if(memb_ptr && elm->default_value_cmp
|
||||
|
@ -523,8 +526,7 @@ SEQUENCE_encode_oer(const asn_TYPE_descriptor_t *td,
|
|||
computed_size += extadds.flushed_bytes;
|
||||
|
||||
/* Now, encode extensions */
|
||||
for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
|
||||
edx++) {
|
||||
for(edx = specs->first_extension; edx < td->elements_count; edx++) {
|
||||
asn_TYPE_member_t *elm = &td->elements[edx];
|
||||
const void *memb_ptr = element_ptr(sptr, elm);
|
||||
|
||||
|
|
|
@ -70,6 +70,6 @@ SEQUENCE { ..., one NULL, two [2] NULL, ..., three [3] NULL }
|
|||
SEQUENCE { ..., one NULL, ..., two [2] NULL, three [3] NULL }
|
||||
SEQUENCE { ..., one BOOLEAN, ..., two [2] BOOLEAN, three [3] BOOLEAN }
|
||||
SEQUENCE { ..., one BOOLEAN, two BIT STRING (SIZE(1..3)) }
|
||||
-- not yet SEQUENCE { ..., null NULL, ..., one BOOLEAN, two BIT STRING (SIZE(1..3)) }
|
||||
SEQUENCE { ..., null NULL, ..., one BOOLEAN, two BIT STRING (SIZE(1..3)) }
|
||||
SEQUENCE { ..., one NULL, two BOOLEAN, three BIT STRING (SIZE(1..3)) }
|
||||
-- not yet SEQUENCE { ..., null NULL, ..., one [1] NULL, two BOOLEAN, three BIT STRING (SIZE(1..3)) }
|
||||
SEQUENCE { ..., null NULL, ..., one [1] NULL, two BOOLEAN, three BIT STRING (SIZE(1..3)) }
|
||||
|
|
Loading…
Reference in New Issue