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 = {
#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 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = {
* 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 @@ struct _stack {
};
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 @@ _add_stack_el(struct _stack *st) {
*/
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 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
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 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
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 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
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) {
......@@ -332,15 +331,28 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
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.
*/
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 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
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 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
}
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;
......
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