OER CHOICE extensions support + fuzzing
diff --git a/skeletons/constr_CHOICE_oer.c b/skeletons/constr_CHOICE_oer.c
index ca5674d..39310b0 100644
--- a/skeletons/constr_CHOICE_oer.c
+++ b/skeletons/constr_CHOICE_oer.c
@@ -238,15 +238,20 @@
(void)CHOICE_variant_set_presence(td, st, ctx->step + 1);
if(specs->ext_start >= 0 && specs->ext_start <= ctx->step) {
- /* We're in the extensions group. #20.2 requires Open Type */
- ASN_DEBUG("Not implemented %s es=%d, edx=%u at %s:%d", td->name,
- specs->ext_start, ctx->step, __FILE__, __LINE__);
- RETURN(RC_FAIL);
+ ssize_t got =
+ oer_open_type_get(opt_codec_ctx, elm->type,
+ elm->encoding_constraints.oer_constraints,
+ memb_ptr2, ptr, size);
+ if(got < 0) ASN__DECODE_FAILED;
+ if(got == 0) ASN__DECODE_STARVED;
+ rval.code = RC_OK;
+ rval.consumed = got;
+ } else {
+ rval = elm->type->op->oer_decoder(
+ opt_codec_ctx, elm->type,
+ elm->encoding_constraints.oer_constraints, memb_ptr2, ptr,
+ size);
}
-
- rval = elm->type->op->oer_decoder(opt_codec_ctx, elm->type,
- elm->encoding_constraints.oer_constraints, memb_ptr2, ptr,
- size);
rval.consumed += consumed_myself;
switch(rval.code) {
case RC_OK:
@@ -319,10 +324,9 @@
void *memb_ptr;
ber_tlv_tag_t tag;
ssize_t tag_len;
- asn_enc_rval_t er;
+ asn_enc_rval_t er = {0, 0, 0};
(void)constraints;
- (void)specs;
if(!sptr) ASN__ENCODE_FAILED;
@@ -355,10 +359,18 @@
ASN__ENCODE_FAILED;
}
- er = elm->type->op->oer_encoder(elm->type, elm->encoding_constraints.oer_constraints, memb_ptr,
- cb, app_key);
- if(er.encoded >= 0)
- er.encoded += tag_len;
+ if(specs->ext_start >= 0 && specs->ext_start <= (present-1)) {
+ ssize_t encoded = oer_open_type_put(elm->type,
+ elm->encoding_constraints.oer_constraints,
+ memb_ptr, cb, app_key);
+ if(encoded < 0) ASN__ENCODE_FAILED;
+ er.encoded = tag_len + encoded;
+ } else {
+ er = elm->type->op->oer_encoder(
+ elm->type, elm->encoding_constraints.oer_constraints, memb_ptr, cb,
+ app_key);
+ if(er.encoded >= 0) er.encoded += tag_len;
+ }
return er;
}
diff --git a/skeletons/oer_decoder.c b/skeletons/oer_decoder.c
index 386e846..52950f4 100644
--- a/skeletons/oer_decoder.c
+++ b/skeletons/oer_decoder.c
@@ -64,6 +64,8 @@
asn_dec_rval_t dr;
size_t container_len = 0;
ssize_t len_len;
+ enum asn_struct_free_method dispose_method =
+ (*struct_ptr) ? ASFM_FREE_UNDERLYING_AND_RESET : ASFM_FREE_EVERYTHING;
/* Get the size of a length determinant */
len_len = oer_fetch_length(bufptr, size, &container_len);
@@ -86,8 +88,7 @@
return len_len + container_len;
} else {
/* Even if RC_WMORE, we can't get more data into a closed container. */
- ASN_STRUCT_FREE(*td, *struct_ptr);
- *struct_ptr = 0;
+ td->op->free_struct(td, *struct_ptr, dispose_method);
return -1;
}
}
diff --git a/skeletons/oer_decoder.h b/skeletons/oer_decoder.h
index c5e9744..6c95d62 100644
--- a/skeletons/oer_decoder.h
+++ b/skeletons/oer_decoder.h
@@ -41,8 +41,8 @@
/*
* Swallow the Open Type (X.696 (08/2015), #30) into /dev/null.
* RETURN VALUES:
- * 0: More data expected than bufptr contains.
* -1: Fatal error deciphering length.
+ * 0: More data expected than bufptr contains.
* >0: Number of bytes used from bufptr.
*/
ssize_t oer_open_type_skip(const void *bufptr, size_t size);
diff --git a/skeletons/oer_encoder.c b/skeletons/oer_encoder.c
index a6f7a78..d0e6ea0 100644
--- a/skeletons/oer_encoder.c
+++ b/skeletons/oer_encoder.c
@@ -109,3 +109,34 @@
}
}
+static int
+oer__count_bytes(const void *buffer, size_t size, void *bytes_ptr) {
+ size_t *bytes = bytes_ptr;
+ *bytes += size;
+ return 0;
+}
+
+ssize_t
+oer_open_type_put(asn_TYPE_descriptor_t *td,
+ const asn_oer_constraints_t *constraints,
+ void *sptr, asn_app_consume_bytes_f *cb,
+ void *app_key) {
+ size_t serialized_byte_count = 0;
+ asn_enc_rval_t er;
+ ssize_t len_len;
+
+ er = td->op->oer_encoder(td, constraints, sptr, oer__count_bytes,
+ &serialized_byte_count);
+ if(er.encoded == -1) return -1;
+ assert(serialized_byte_count == er.encoded);
+
+ len_len = oer_serialize_length(serialized_byte_count, cb, app_key);
+ if(len_len == -1) return -1;
+
+ er = td->op->oer_encoder(td, constraints, sptr, cb, app_key);
+ if(er.encoded == -1) return -1;
+ assert(serialized_byte_count == er.encoded);
+
+ return er.encoded + len_len;
+}
+
diff --git a/skeletons/oer_encoder.h b/skeletons/oer_encoder.h
index 3150b5c..37d95e3 100644
--- a/skeletons/oer_encoder.h
+++ b/skeletons/oer_encoder.h
@@ -45,6 +45,18 @@
void *app_key /* Arbitrary callback argument */
);
+/*
+ * Write out the Open Type (X.696 (08/2015), #30).
+ * RETURN VALUES:
+ * -1: Fatal error encoding the type.
+ * >=0: Number of bytes serialized.
+ */
+ssize_t oer_open_type_put(struct asn_TYPE_descriptor_s *td,
+ const asn_oer_constraints_t *constraints,
+ void *struct_ptr,
+ asn_app_consume_bytes_f *consume_bytes_cb,
+ void *app_key);
+
/*
* Length-prefixed buffer encoding for primitive types.
diff --git a/tests/tests-randomized/bundles/15-CHOICE-bundle.txt b/tests/tests-randomized/bundles/15-CHOICE-bundle.txt
index 5f9ea26..55b8f45 100644
--- a/tests/tests-randomized/bundles/15-CHOICE-bundle.txt
+++ b/tests/tests-randomized/bundles/15-CHOICE-bundle.txt
@@ -1 +1,11 @@
CHOICE { null NULL }
+CHOICE { null NULL, ... }
+CHOICE { one NULL, two [2] NULL }
+CHOICE { one NULL, two [2] NULL, ... }
+CHOICE { one NULL, ..., two [2] NULL }
+CHOICE { one NULL, two [2] NULL, ..., three [3] NULL }
+CHOICE { one NULL, ..., two [2] NULL, three [3] NULL }
+CHOICE { one BOOLEAN, ..., two [2] BOOLEAN, three [3] BOOLEAN }
+CHOICE { one BOOLEAN, two BIT STRING (SIZE(1..3)) }
+CHOICE { ..., one BOOLEAN, two BIT STRING (SIZE(1..3)) }
+CHOICE { one NULL, two BOOLEAN, three BIT STRING (SIZE(1..3)) }