managing nested expectations better
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@387 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index 8906c6f..df6f86e 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -47,7 +47,7 @@
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
- size_t num = num_bytes; \
+ size_t num = (num_bytes); \
buf_ptr = ((char *)buf_ptr) + num; \
size -= num; \
consumed_myself += num; \
@@ -93,7 +93,8 @@
* No, I am not going to explain what the following stuff is.
*/
struct _stack_el {
- ber_tlv_len_t left; /* What's left to read */
+ ber_tlv_len_t left; /* What's left to read (or -1) */
+ ber_tlv_len_t frame; /* What was planned to read (or -1) */
int cont_level; /* Depth of subcontainment */
int want_nulls; /* Want null "end of content" octets? */
int bits_chopped; /* Flag in BIT STRING mode */
@@ -106,7 +107,7 @@
};
static struct _stack_el *
-_add_stack_el(struct _stack *st) {
+OS__add_stack_el(struct _stack *st) {
struct _stack_el *nel;
/*
@@ -114,8 +115,6 @@
*/
if(st->cur_ptr && st->cur_ptr->next) {
nel = st->cur_ptr->next;
- nel->left = 0;
- nel->want_nulls = 0;
nel->bits_chopped = 0;
/* Retain nel->cont_level, it's correct. */
} else {
@@ -196,9 +195,6 @@
RETURN(rval.code);
}
- ASN_DEBUG("OS length is %d bytes, form %d (consumed %d==0)",
- (int)ctx->left, tlv_constr, rval.consumed);
-
if(tlv_constr) {
/*
* Complex operation, requires stack of expectations.
@@ -238,11 +234,14 @@
ber_tlv_len_t tlv_len;
ber_tlv_tag_t expected_tag;
ssize_t tl, ll;
+ ssize_t Left = ((!sel||sel->left==-1||sel->left >= size)
+ ?size:sel->left);
- ASN_DEBUG("fetch tag(size=%d), %sstack, left=%d, want0=%d",
- (int)size, sel?"":"!",
+
+ ASN_DEBUG("fetch tag(size=%d,L=%d), %sstack, left=%d, want0=%d",
+ (int)size, Left, sel?"":"!",
sel?sel->left:0, sel?sel->want_nulls:0);
- tl = ber_fetch_tag(buf_ptr, size, &tlv_tag);
+ tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
switch(tl) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
@@ -251,10 +250,10 @@
tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
ll = ber_fetch_length(tlv_constr,
- (char *)buf_ptr + tl, size - tl, &tlv_len);
+ (char *)buf_ptr + tl, Left - tl, &tlv_len);
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,
+ (int)Left, tl, tlv_len, ll,
((uint8_t *)buf_ptr)[0],
((uint8_t *)buf_ptr)[1]);
switch(ll) {
@@ -333,14 +332,27 @@
}
/*
+ * Consult with the old expectation.
+ * Check that it knows what we are doing here, and how much.
+ */
+ if(sel && sel->left != -1) {
+ if(sel->left < (tl + ll))
+ RETURN(RC_FAIL);
+ sel->left -= (tl + ll);
+ if(sel->left < tlv_len)
+ RETURN(RC_FAIL);
+ }
+
+
+ /*
* Append a new expectation.
*/
- sel = _add_stack_el(stck);
+ sel = OS__add_stack_el(stck);
if(sel) {
sel->want_nulls = (tlv_len==-1);
- sel->left = tlv_len;
- ASN_DEBUG("+EXPECT2 left=%d wn=%d, clvl=%d",
- sel->left, sel->want_nulls, sel->cont_level);
+ sel->frame = sel->left = tlv_len;
+ ASN_DEBUG("+EXPECT2 frame=%d wn=%d, clvl=%d",
+ sel->frame, sel->want_nulls, sel->cont_level);
} else {
RETURN(RC_FAIL);
}
@@ -388,14 +400,30 @@
sel->left -= len;
}
- if(sel->left) {
+ if(sel->left)
RETURN(RC_WMORE);
- } else {
- sel->left = 0;
- if(sel->prev)
+
+ while(sel->left == 0) {
+ ASN_DEBUG("sel %p, l=%d, f=%d, %p->l=%d p->f=%d\n",
+ sel, sel->left, sel->frame,
+ sel->prev,
+ sel->prev?sel->prev->left:0,
+ sel->prev?sel->prev->frame:0
+ );
+ if(sel->prev) {
+ if(sel->prev->left != -1) {
+ if(sel->prev->left < sel->frame)
+ RETURN(RC_FAIL);
+ sel->prev->left -= sel->frame;
+ }
sel = stck->cur_ptr = sel->prev;
- PREV_PHASE(ctx);
- goto phase1;
+ if(sel->left) {
+ PREV_PHASE(ctx);
+ goto phase1;
+ }
+ } else {
+ break;
+ }
}
}
break;
@@ -428,7 +456,8 @@
}
ASN_DEBUG("Took %d bytes to encode %s: [%s]:%d",
- consumed_myself, td->name, st->buf, st->size);
+ consumed_myself, td->name,
+ (type_type == _TT_GENERIC) ? (char *)st->buf : "", st->size);
rval.code = RC_OK;
rval.consumed = consumed_myself;