fix after UPER round-trip fuzz
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index d080ccb..bf4de7a 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
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 @@
FREEMEM(epres);
ASN__DECODE_STARVED;
}
+ ASN_DEBUG("Skipped overflow extension");
+ continue;
}
break;
}
@@ -1281,28 +1267,33 @@
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 @@
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 @@
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 @@
/*
* 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 @@
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;