diff options
author | Lev Walkin <vlm@lionet.info> | 2004-09-27 20:54:06 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2004-09-27 20:54:06 +0000 |
commit | 5c91599332cb435e251c85de0c2857de62e0c35e (patch) | |
tree | 4707d2495b189adcff399157c85cd0b3fc0014db | |
parent | ed46543c404eb5cf6fc1d563ef388d00bdd05c33 (diff) |
better handling of encoded subTLVs
-rw-r--r-- | skeletons/OCTET_STRING.c | 162 |
1 files changed, 87 insertions, 75 deletions
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c index 6a72d1a1..984b7f57 100644 --- a/skeletons/OCTET_STRING.c +++ b/skeletons/OCTET_STRING.c @@ -93,10 +93,11 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = { */ struct _stack_el { ber_tlv_len_t left; /* What's left to read (or -1) */ - ber_tlv_len_t frame; /* What was planned to read (or -1) */ + ber_tlv_len_t got; /* What was actually processed */ int cont_level; /* Depth of subcontainment */ int want_nulls; /* Want null "end of content" octets? */ int bits_chopped; /* Flag in BIT STRING mode */ + ber_tlv_tag_t tag; /* For debugging purposes */ struct _stack_el *prev; struct _stack_el *next; }; @@ -115,7 +116,8 @@ OS__add_stack_el(struct _stack *st) { if(st->cur_ptr && st->cur_ptr->next) { nel = st->cur_ptr->next; nel->bits_chopped = 0; - /* Retain nel->cont_level, it's correct. */ + nel->got = 0; + /* Retain the nel->cont_level, it's correct. */ } else { (void *)nel = CALLOC(1, sizeof(struct _stack_el)); if(nel == NULL) @@ -156,7 +158,7 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ber_dec_ctx_t *ctx; ssize_t consumed_myself = 0; struct _stack *stck; /* A stack structure */ - struct _stack_el *sel; /* Stack element */ + struct _stack_el *sel = 0; /* Stack element */ int tlv_constr; enum type_type_e { _TT_GENERIC = 0, /* Just a random OCTET STRING */ @@ -231,16 +233,40 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ber_tlv_tag_t tlv_tag; ber_tlv_len_t tlv_len; ber_tlv_tag_t expected_tag; - ssize_t tl, ll; + ssize_t tl, ll, tlvl; /* This one works even if (sel->left == -1) */ ssize_t Left = ((!sel||(size_t)sel->left >= size) - ?size:(size_t)sel->left); + ?(ssize_t)size:sel->left); - 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); + ASN_DEBUG("%p, s->l=%d, s->wn=%d, s->g=%d\n", sel, + sel?sel->left:0, + sel?sel->want_nulls:0, + sel?sel->got:0 + ); + if(sel && sel->left <= 0 && sel->want_nulls == 0) { + if(sel->prev) { + struct _stack_el *prev = sel->prev; + if(prev->left != -1) { + if(prev->left < sel->got) + RETURN(RC_FAIL); + prev->left -= sel->got; + } + prev->got += sel->got; + sel = stck->cur_ptr = prev; + if(!sel) break; + tlv_constr = 1; + continue; + } else { + sel = stck->cur_ptr = 0; + break; /* Nothing to wait */ + } + } + tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag); + ASN_DEBUG("fetch tag(size=%d,L=%d), %sstack, left=%d, wn=%d, tl=%d", + (int)size, Left, sel?"":"!", + sel?sel->left:0, sel?sel->want_nulls:0, tl); switch(tl) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); @@ -250,11 +276,9 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, ll = ber_fetch_length(tlv_constr, (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, left=%ld, tl=%d, len=%d, ll=%d", ber_tlv_tag_string(tlv_tag), tlv_constr, - (int)Left, tl, tlv_len, ll, - ((uint8_t *)buf_ptr)[0], - ((uint8_t *)buf_ptr)[1]); + (long)Left, tl, tlv_len, ll); switch(ll) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); @@ -264,26 +288,21 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, && ((uint8_t *)buf_ptr)[0] == 0 && ((uint8_t *)buf_ptr)[1] == 0) { - ADVANCE(2); - if(type_type == _TT_ANY) APPEND("\0\0", 2); ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls); + if(type_type == _TT_ANY) APPEND("\0\0", 2); + + ADVANCE(2); + sel->got += 2; + if(sel->left != -1) { + sel->left -= 2; /* assert(sel->left >= 2) */ + } + sel->want_nulls--; if(sel->want_nulls == 0) { /* Move to the next expectation */ - sel = stck->cur_ptr = sel->prev; - if(sel == NULL) - break; - } - - if(sel->want_nulls) { - /* - * Simulate while(TRUE) for this loop. - * This is necessary to fetch the next - * expectation after current "end of content", - * for which tlv_constr is 0. - */ + sel->left = 0; tlv_constr = 1; } @@ -331,33 +350,34 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, } /* - * 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 = OS__add_stack_el(stck); - if(sel) { - sel->want_nulls = (tlv_len==-1); - sel->frame = sel->left = tlv_len; - ASN_DEBUG("+EXPECT2 frame=%d wn=%d, clvl=%d", - sel->frame, sel->want_nulls, sel->cont_level); + if(!sel) RETURN(RC_FAIL); + + tlvl = tl + ll; /* Combined length of T and L encoding */ + + sel->tag = tlv_tag; + + sel->want_nulls = (tlv_len==-1); + if(sel->prev && sel->prev->left != -1) { + /* Check that the parent frame is big enough */ + if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len)) + RETURN(RC_FAIL); + if(tlv_len == -1) + sel->left = sel->prev->left - tlvl; + else + sel->left = tlv_len; } else { - RETURN(RC_FAIL); + sel->left = tlv_len; } + if(type_type == _TT_ANY) APPEND(buf_ptr, tlvl); + sel->got += tlvl; + ADVANCE(tlvl); + + ASN_DEBUG("+EXPECT2 got=%d left=%d, wn=%d, clvl=%d", + sel->got, sel->left, sel->want_nulls, sel->cont_level); - if(type_type == _TT_ANY) APPEND(buf_ptr, tl + ll); - ADVANCE(tl+ll); } while(tlv_constr); if(sel == NULL) { /* Finished operation, "phase out" */ @@ -371,8 +391,9 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, case 2: (void *)stck = ctx->ptr; sel = stck->cur_ptr; - ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld", - (long)sel->left, (long)size); + ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d", + (long)sel->left, (long)size, (long)sel->got, + sel->want_nulls); { ber_tlv_len_t len; @@ -397,33 +418,17 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, } ADVANCE(len); sel->left -= len; + sel->got += len; } - if(sel->left) + if(sel->left) { + ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n", + (long)sel->left, (long)size, sel->want_nulls); RETURN(RC_WMORE); - - 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; - if(sel->left) { - PREV_PHASE(ctx); - goto phase1; - } - } else { - break; - } } + + PREV_PHASE(ctx); + goto phase1; } break; case 3: @@ -446,6 +451,15 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, break; } + if(sel) { + ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld", + sel->prev, sel->want_nulls, + (long)sel->left, (long)sel->got, (long)size); + if(sel->prev || sel->want_nulls > 1 || sel->left > 0) { + RETURN(RC_WMORE); + } + } + /* * BIT STRING-specific processing. */ @@ -458,10 +472,8 @@ OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td, consumed_myself, td->name, (type_type == _TT_GENERIC) ? (char *)st->buf : "", st->size); - rval.code = RC_OK; - rval.consumed = consumed_myself; - return rval; + RETURN(RC_OK); } /* |