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)) }