support for ANY type decoding
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index fd25e57..71d59d3 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -51,11 +51,12 @@
} while(0)
#define APPEND(bufptr, bufsize) do { \
+ size_t _bs = (bufsize); \
size_t _ns = ctx->step; /* Allocated */ \
- if(_ns <= (size_t)(st->size + bufsize)) { \
+ if(_ns <= (size_t)(st->size + _bs)) { \
void *ptr; \
do { _ns = _ns ? _ns<<2 : 16; } \
- while(_ns <= (size_t)(st->size + bufsize)); \
+ while(_ns <= (size_t)(st->size + _bs)); \
ptr = REALLOC(st->buf, _ns); \
if(ptr) { \
st->buf = (uint8_t *)ptr; \
@@ -64,8 +65,8 @@
RETURN(RC_FAIL); \
} \
} \
- memcpy(st->buf + st->size, bufptr, bufsize); \
- st->size += bufsize; \
+ memcpy(st->buf + st->size, bufptr, _bs); \
+ st->size += _bs; \
if(st->size < 0) \
/* Why even care?.. JIC */ \
RETURN(RC_FAIL); \
@@ -124,12 +125,6 @@
if(st == NULL)
return NULL;
- st->cur_ptr = _add_stack_el(st);
- if(st->cur_ptr == NULL) {
- FREEMEM(st);
- return NULL;
- }
-
return st;
}
@@ -142,20 +137,16 @@
OCTET_STRING_t *st = (OCTET_STRING_t *)*os_structure;
ber_dec_rval_t rval;
ber_dec_ctx_t *ctx;
+ ber_tlv_tag_t terminal_tag; /* Inner tag for constructed types */
ssize_t consumed_myself = 0;
struct _stack *stck; /* A stack structure */
struct _stack_el *sel; /* Stack element */
int tlv_constr;
- /*
- * This is a some sort of a hack.
- * The OCTET STRING decoder is being used in BIT STRING mode.
- */
- int is_bit_str = (td->specifics==(void *)-1);
+ int is_bit_str = 0; /* See below under switch(td->specifics) */
+ int is_ANY_type = 0; /* See below under switch(td->specifics) */
ASN_DEBUG("Decoding %s as %s (%ld)",
- td->name,
- is_bit_str ? "BIT STRING" : "OCTET STRING",
- (long)size);
+ td->name, "OCTET STRING", (long)size);
/*
* Create the string if does not exist.
@@ -169,6 +160,25 @@
/* Restore parsing context */
ctx = &st->_ber_dec_ctx;
+ switch((int)td->specifics) {
+ case 0:
+ terminal_tag = asn1_DEF_OCTET_STRING_tags[0]; /* [U4] */
+ break;
+ case -1: /* BIT STRING */
+ /*
+ * This is some sort of a hack.
+ * The OCTET STRING decoder is being used in BIT STRING mode.
+ */
+ is_bit_str = 1;
+ terminal_tag = ASN_TAG_CLASS_UNIVERSAL | (3 << 2);
+ break;
+ default: /* Just in case; fall through */
+ case 1: /* ANY type */
+ is_ANY_type = 1;
+ terminal_tag = -1;
+ break;
+ }
+
switch(ctx->phase) {
case 0:
/*
@@ -191,6 +201,7 @@
ctx->ptr = _new_stack();
if(ctx->ptr) {
(void *)stck = ctx->ptr;
+#if 0
if(ctx->left < 0) {
stck->cur_ptr->want_nulls = -ctx->left;
stck->cur_ptr->left = -1;
@@ -198,10 +209,12 @@
stck->cur_ptr->want_nulls = 0;
stck->cur_ptr->left = ctx->left;
}
- ASN_DEBUG("Expectation left=%d wn=%d added",
+ ASN_DEBUG("+EXPECT1 left=%d wn=%d",
stck->cur_ptr->left,
stck->cur_ptr->want_nulls);
+#endif
if(is_bit_str) {
+ /* Number of meaningless tail bits */
APPEND("\0", 1);
}
} else {
@@ -212,11 +225,11 @@
* Jump into stackless primitive decoding.
*/
_CH_PHASE(ctx, 3);
+ if(is_ANY_type) APPEND(buf_ptr, rval.consumed);
ADVANCE(rval.consumed);
goto phase3;
}
- ADVANCE(rval.consumed);
NEXT_PHASE(ctx);
/* Fall through */
case 1:
@@ -231,6 +244,9 @@
ber_tlv_len_t tlv_len;
ssize_t tl, ll;
+ ASN_DEBUG("fetch tag(size=%d), %sstack, left=%d, want0=%d",
+ (int)size, sel?"":"!",
+ sel?sel->left:0, sel?sel->want_nulls:0);
tl = ber_fetch_tag(buf_ptr, size, &tlv_tag);
switch(tl) {
case -1: RETURN(RC_FAIL);
@@ -241,8 +257,9 @@
ll = ber_fetch_length(tlv_constr,
(char *)buf_ptr + tl, size - tl, &tlv_len);
- ASN_DEBUG("Got tag=%s, tl=%d, len=%d, ll=%d, {%d, %d}",
- ber_tlv_tag_string(tlv_tag), tl, tlv_len, ll,
+ ASN_DEBUG("Got tag=%s, tc=%d, size=%d, tl=%d, len=%d, ll=%d, {%d, %d}",
+ ber_tlv_tag_string(tlv_tag), tlv_constr,
+ (int)size, tl, tlv_len, ll,
((uint8_t *)buf_ptr)[0],
((uint8_t *)buf_ptr)[1]);
switch(ll) {
@@ -250,30 +267,36 @@
case 0: RETURN(RC_WMORE);
}
- if(sel->want_nulls
+ if(sel && sel->want_nulls
&& ((uint8_t *)buf_ptr)[0] == 0
&& ((uint8_t *)buf_ptr)[1] == 0)
{
+ ADVANCE(2);
+ if(is_ANY_type) APPEND("\0\0", 2);
+
+ ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
+
sel->want_nulls--;
if(sel->want_nulls == 0) {
/* Move to the next expectation */
sel = stck->cur_ptr = sel->prev;
- if(sel == NULL) {
- ADVANCE(2);
+ if(sel == NULL)
break;
- }
}
+
if(sel->want_nulls) {
/*
* Simulate while(TRUE) for this loop.
* This is necessary to fetch the next
- * "end of content" expectation.
+ * expectation after current "end of content",
+ * for which tlv_constr is 0.
*/
- ADVANCE(2);
tlv_constr = 1;
- continue;
}
- } else if(tlv_tag != td->tags[td->tags_count-1]) {
+
+ continue;
+ } else if(tlv_tag != terminal_tag
+ && terminal_tag != (ber_tlv_tag_t)-1) {
char buf[2][32];
ber_tlv_tag_snprint(tlv_tag,
buf[0], sizeof(buf[0]));
@@ -291,12 +314,13 @@
if(sel) {
sel->want_nulls = (tlv_len==-1);
sel->left = tlv_len;
- ASN_DEBUG("Expectation %d %d added",
+ ASN_DEBUG("+EXPECT2 left=%d wn=%d",
sel->left, sel->want_nulls);
} else {
RETURN(RC_FAIL);
}
+ if(is_ANY_type) APPEND(buf_ptr, tl + ll);
ADVANCE(tl+ll);
} while(tlv_constr);
if(sel == NULL) {