Commit 3990ba68 authored by Lev Walkin's avatar Lev Walkin

managing nested expectations better

parent 938c6fea
...@@ -47,7 +47,7 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = { ...@@ -47,7 +47,7 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = {
#undef ADVANCE #undef ADVANCE
#define ADVANCE(num_bytes) do { \ #define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \ size_t num = (num_bytes); \
buf_ptr = ((char *)buf_ptr) + num; \ buf_ptr = ((char *)buf_ptr) + num; \
size -= num; \ size -= num; \
consumed_myself += num; \ consumed_myself += num; \
...@@ -93,7 +93,8 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = { ...@@ -93,7 +93,8 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = {
* No, I am not going to explain what the following stuff is. * No, I am not going to explain what the following stuff is.
*/ */
struct _stack_el { 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 cont_level; /* Depth of subcontainment */
int want_nulls; /* Want null "end of content" octets? */ int want_nulls; /* Want null "end of content" octets? */
int bits_chopped; /* Flag in BIT STRING mode */ int bits_chopped; /* Flag in BIT STRING mode */
...@@ -106,7 +107,7 @@ struct _stack { ...@@ -106,7 +107,7 @@ struct _stack {
}; };
static struct _stack_el * static struct _stack_el *
_add_stack_el(struct _stack *st) { OS__add_stack_el(struct _stack *st) {
struct _stack_el *nel; struct _stack_el *nel;
/* /*
...@@ -114,8 +115,6 @@ _add_stack_el(struct _stack *st) { ...@@ -114,8 +115,6 @@ _add_stack_el(struct _stack *st) {
*/ */
if(st->cur_ptr && st->cur_ptr->next) { if(st->cur_ptr && st->cur_ptr->next) {
nel = st->cur_ptr->next; nel = st->cur_ptr->next;
nel->left = 0;
nel->want_nulls = 0;
nel->bits_chopped = 0; nel->bits_chopped = 0;
/* Retain nel->cont_level, it's correct. */ /* Retain nel->cont_level, it's correct. */
} else { } else {
...@@ -196,9 +195,6 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ...@@ -196,9 +195,6 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
RETURN(rval.code); 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) { if(tlv_constr) {
/* /*
* Complex operation, requires stack of expectations. * Complex operation, requires stack of expectations.
...@@ -238,11 +234,14 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ...@@ -238,11 +234,14 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
ber_tlv_len_t tlv_len; ber_tlv_len_t tlv_len;
ber_tlv_tag_t expected_tag; ber_tlv_tag_t expected_tag;
ssize_t tl, ll; 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", ASN_DEBUG("fetch tag(size=%d,L=%d), %sstack, left=%d, want0=%d",
(int)size, sel?"":"!", (int)size, Left, sel?"":"!",
sel?sel->left:0, sel?sel->want_nulls:0); 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) { switch(tl) {
case -1: RETURN(RC_FAIL); case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE); case 0: RETURN(RC_WMORE);
...@@ -251,10 +250,10 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ...@@ -251,10 +250,10 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr); tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
ll = ber_fetch_length(tlv_constr, 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}", 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, 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)[0],
((uint8_t *)buf_ptr)[1]); ((uint8_t *)buf_ptr)[1]);
switch(ll) { switch(ll) {
...@@ -332,15 +331,28 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ...@@ -332,15 +331,28 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
RETURN(RC_FAIL); RETURN(RC_FAIL);
} }
/*
* 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. * Append a new expectation.
*/ */
sel = _add_stack_el(stck); sel = OS__add_stack_el(stck);
if(sel) { if(sel) {
sel->want_nulls = (tlv_len==-1); sel->want_nulls = (tlv_len==-1);
sel->left = tlv_len; sel->frame = sel->left = tlv_len;
ASN_DEBUG("+EXPECT2 left=%d wn=%d, clvl=%d", ASN_DEBUG("+EXPECT2 frame=%d wn=%d, clvl=%d",
sel->left, sel->want_nulls, sel->cont_level); sel->frame, sel->want_nulls, sel->cont_level);
} else { } else {
RETURN(RC_FAIL); RETURN(RC_FAIL);
} }
...@@ -388,14 +400,30 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ...@@ -388,14 +400,30 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
sel->left -= len; sel->left -= len;
} }
if(sel->left) { if(sel->left)
RETURN(RC_WMORE); RETURN(RC_WMORE);
} else {
sel->left = 0; while(sel->left == 0) {
if(sel->prev) 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; sel = stck->cur_ptr = sel->prev;
PREV_PHASE(ctx); if(sel->left) {
goto phase1; PREV_PHASE(ctx);
goto phase1;
}
} else {
break;
}
} }
} }
break; break;
...@@ -428,7 +456,8 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ...@@ -428,7 +456,8 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
} }
ASN_DEBUG("Took %d bytes to encode %s: [%s]:%d", 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.code = RC_OK;
rval.consumed = consumed_myself; rval.consumed = consumed_myself;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment