diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index 5a0eccee27e3e2e4fa6baa65525d6492386dc8c5..9c8b9ed3a5d778c30185842ca04cc5d8f9ca058b 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -571,7 +571,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(ct && ct->flags & APC_EXTENSIBLE) { int inext = per_get_few_bits(pd, 1); - if(inext < 0) _ASN_DECODE_FAILED; + if(inext < 0) _ASN_DECODE_STARVED; if(inext) ct = 0; } @@ -599,7 +599,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ASN_DEBUG("Integer with range %d bits", ct->range_bits); if(ct->range_bits >= 0) { long value = per_get_few_bits(pd, ct->range_bits); - if(value < 0) _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; ASN_DEBUG("Got value %ld + low %ld", value, ct->lower_bound); value += ct->lower_bound; @@ -619,14 +619,14 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Get the PER length */ len = uper_get_length(pd, -1, &repeat); - if(len < 0) _ASN_DECODE_FAILED; + if(len < 0) _ASN_DECODE_STARVED; p = REALLOC(st->buf, st->size + len + 1); if(!p) _ASN_DECODE_FAILED; st->buf = (uint8_t *)p; ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len); - if(ret < 0) _ASN_DECODE_FAILED; + if(ret < 0) _ASN_DECODE_STARVED; st->size += len; } while(repeat); st->buf[st->size] = 0; /* JIC */ diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c index fa16eb07b4b4f7e823b58b647ce8b59498046407..e3af1ca49b2c722513876e70219bb0ac8e74cbd9 100644 --- a/skeletons/NativeEnumerated.c +++ b/skeletons/NativeEnumerated.c @@ -96,13 +96,13 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, if(ct->flags & APC_EXTENSIBLE) { int inext = per_get_few_bits(pd, 1); - if(inext < 0) _ASN_DECODE_FAILED; + if(inext < 0) _ASN_DECODE_STARVED; if(inext) ct = 0; } if(ct && ct->range_bits >= 0) { value = per_get_few_bits(pd, ct->range_bits); - if(value < 0) _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; if(value >= (specs->extension ? specs->extension - 1 : specs->map_count)) _ASN_DECODE_FAILED; @@ -113,7 +113,7 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, * X.691, #10.6: normally small non-negative whole number; */ value = uper_get_nsnnwn(pd); - if(value < 0) _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; value += specs->extension - 1; if(value >= specs->map_count) _ASN_DECODE_FAILED; diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c index 7b83b618a7573622be3825a5a9c385847bc42b29..3bef5608ce2e1b95c4bf1b326e2144d4522dc425 100644 --- a/skeletons/OCTET_STRING.c +++ b/skeletons/OCTET_STRING.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>. + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>. * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -1231,7 +1231,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, if(ct->flags & APC_EXTENSIBLE) { int inext = per_get_few_bits(pd, 1); - if(inext < 0) RETURN(RC_FAIL); + if(inext < 0) RETURN(RC_WMORE); if(inext) ct = &asn_DEF_OCTET_STRING_constraint; consumed_myself = 0; } @@ -1254,7 +1254,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, if(ct->effective_bits == 0) { int ret = per_get_many_bits(pd, st->buf, 0, unit_bits * ct->upper_bound); - if(ret < 0) RETURN(RC_FAIL); + if(ret < 0) RETURN(RC_WMORE); consumed_myself += unit_bits * ct->upper_bound; st->buf[st->size] = 0; if(unit_bits == 1 && (ct->upper_bound & 0x7)) @@ -1271,11 +1271,12 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, /* Get the PER length */ len_bits = uper_get_length(pd, ct->effective_bits, &repeat); - if(len_bits < 0) RETURN(RC_FAIL); + if(len_bits < 0) RETURN(RC_WMORE); len_bits += ct->lower_bound; - ASN_DEBUG("Got per length eb %ld, len %ld", - (long)ct->effective_bits, (long)len_bits); + ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)", + (long)ct->effective_bits, (long)len_bits, + repeat ? "repeat" : "once", td->name); if(unit_bits == 1) { len_bytes = (len_bits + 7) >> 3; if(len_bits & 0x7) @@ -1290,7 +1291,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, st->buf = (uint8_t *)p; ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits); - if(ret < 0) RETURN(RC_FAIL); + if(ret < 0) RETURN(RC_WMORE); st->size += len_bytes; } while(repeat); st->buf[st->size] = 0; /* nul-terminate */ @@ -1327,8 +1328,8 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07); } - ASN_DEBUG("Encoding %s into %d units", - td->name, sizeinunits); + ASN_DEBUG("Encoding %s into %d units of %d bits", + td->name, sizeinunits, unit_bits); /* Figure out wheter size lies within PER visible consrtaint */ @@ -1361,7 +1362,7 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, ret = per_put_few_bits(po, sizeinunits - ct->lower_bound, ct->effective_bits); if(ret) _ASN_ENCODE_FAILED; - ret = per_put_many_bits(po, st->buf, sizeinunits); + ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits); if(ret) _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(er); } @@ -1381,7 +1382,7 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits); - ret = per_put_many_bits(po, buf, maySave); + ret = per_put_many_bits(po, buf, maySave * unit_bits); if(ret) _ASN_ENCODE_FAILED; if(unit_bits == 1) diff --git a/skeletons/asn_codecs.h b/skeletons/asn_codecs.h index bd6b946f967533d52f55951224400c600971dcf8..1ee7377601870cd1d745882076bd74cd73098f9e 100644 --- a/skeletons/asn_codecs.h +++ b/skeletons/asn_codecs.h @@ -93,6 +93,12 @@ typedef struct asn_dec_rval_s { tmp_error.consumed = 0; \ return tmp_error; \ } while(0) +#define _ASN_DECODE_STARVED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_WMORE; \ + tmp_error.consumed = 0; \ + return tmp_error; \ +} while(0) #ifdef __cplusplus } diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c index a0a6d76a201d985ecf95ed80b6f5cb921e1469d5..b8d6fa9a7f210585e851f8f1ab3cadf1d8fe4923 100644 --- a/skeletons/constr_CHOICE.c +++ b/skeletons/constr_CHOICE.c @@ -852,22 +852,22 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(ct && ct->flags & APC_EXTENSIBLE) { value = per_get_few_bits(pd, 1); - if(value < 0) _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; if(value) ct = 0; /* Not restricted */ } if(ct && ct->range_bits >= 0) { value = per_get_few_bits(pd, ct->range_bits); - if(value < 0) _ASN_DECODE_FAILED; - if(value > ct->upper_bound) - _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; ASN_DEBUG("CHOICE %s got index %d in range %d", td->name, value, ct->range_bits); + if(value > ct->upper_bound) + _ASN_DECODE_FAILED; } else { if(specs->ext_start == -1) _ASN_DECODE_FAILED; value = uper_get_nsnnwn(pd); - if(value < 0) _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; value += specs->ext_start; if(value >= td->elements_count) _ASN_DECODE_FAILED; diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c index 9b7dcf328ecffa24a5e27346d4a5286fab701366..b769434345763a454777a89458155f5debea73c8 100644 --- a/skeletons/constr_SEQUENCE.c +++ b/skeletons/constr_SEQUENCE.c @@ -1048,7 +1048,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Handle extensions */ if(specs->ext_before >= 0) { extpresent = per_get_few_bits(pd, 1); - if(extpresent < 0) _ASN_DECODE_FAILED; + if(extpresent < 0) _ASN_DECODE_STARVED; } /* Prepare a place and read-in the presence bitmap */ @@ -1058,7 +1058,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Get the presence map */ if(per_get_many_bits(pd, opres, 0, specs->roms_count)) { FREEMEM(opres); - _ASN_DECODE_FAILED; + _ASN_DECODE_STARVED; } opmd.buffer = opres; opmd.nboff = 0; diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c index 03c6fe28e227916d7d117d1871f2c80ef134e8f2..09f27db53dada6869accd8dbb3aba0f56b49e00b 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -883,7 +883,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(ct && ct->flags & APC_EXTENSIBLE) { int value = per_get_few_bits(pd, 1); - if(value < 0) _ASN_DECODE_FAILED; + if(value < 0) _ASN_DECODE_STARVED; if(value) ct = 0; /* Not restricted! */ } @@ -892,7 +892,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, nelems = per_get_few_bits(pd, ct->effective_bits); ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s", (long)nelems, ct->lower_bound, td->name); - if(nelems < 0) _ASN_DECODE_FAILED; + if(nelems < 0) _ASN_DECODE_STARVED; nelems += ct->lower_bound; } else { nelems = -1; @@ -905,7 +905,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ct ? ct->effective_bits : -1, &repeat); ASN_DEBUG("Got to decode %d elements (eff %d)", (int)nelems, (int)ct ? ct->effective_bits : -1); - if(nelems < 0) _ASN_DECODE_FAILED; + if(nelems < 0) _ASN_DECODE_STARVED; } for(i = 0; i < nelems; i++) { @@ -921,12 +921,13 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ASN_DEBUG("Failed to add element into %s", td->name); /* Fall through */ + rv.code == RC_FAIL; } else { ASN_DEBUG("Failed decoding %s of %s (SET OF)", elm->type->name, td->name); } if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); - _ASN_DECODE_FAILED; + return rv; } nelems = -1; /* Allow uper_get_length() */ diff --git a/skeletons/per_decoder.c b/skeletons/per_decoder.c index f1b723f21372b79144129403c1a722e960862798..16dee369624bbf28bb8957e222abe77059980d9f 100644 --- a/skeletons/per_decoder.c +++ b/skeletons/per_decoder.c @@ -3,12 +3,14 @@ #include <per_decoder.h> asn_dec_rval_t -uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits) { +uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) { asn_codec_ctx_t s_codec_ctx; asn_dec_rval_t rval; asn_per_data_t pd; - if(skip_bits < 0 || skip_bits > 7 || (skip_bits > 0 && !size)) + if(skip_bits < 0 || skip_bits > 7 + || unused_bits < 0 || unused_bits > 7 + || (unused_bits > 0 && !size)) _ASN_DECODE_FAILED; /* @@ -30,7 +32,9 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp /* Fill in the position indicator */ pd.buffer = (const uint8_t *)buffer; pd.nboff = skip_bits; - pd.nbits = 8 * size; /* 8 is CHAR_BIT from <limits.h> */ + pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */ + if(pd.nboff > pd.nbits) + _ASN_DECODE_FAILED; /* * Invoke type-specific decoder. @@ -38,12 +42,13 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp if(!td->uper_decoder) _ASN_DECODE_FAILED; /* PER is not compiled in */ rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd); - if(rval.code == RC_FAIL) { - rval.consumed = 0; - } else { + if(rval.code == RC_OK) { /* Return the number of consumed bits */ rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3) + pd.nboff - skip_bits; + } else { + /* PER codec is not a restartable */ + rval.consumed = 0; } return rval; } diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h index 23cb7d7a7f27813b0c8f11c80d1147310e611369..26aaf59400445aff62fb007370fc35c0cfa9b1b2 100644 --- a/skeletons/per_decoder.h +++ b/skeletons/per_decoder.h @@ -22,7 +22,8 @@ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, void **struct_ptr, /* Pointer to a target structure's pointer */ const void *buffer, /* Data to be decoded */ size_t size, /* Size of data buffer */ - int skip_bits /* Number of unused leading bits, 0..7 */ + int skip_bits, /* Number of unused leading bits, 0..7 */ + int unused_bits /* Number of unused tailing bits, 0..7 */ ); diff --git a/skeletons/per_support.c b/skeletons/per_support.c index b0149f8969dd4aab6da9c4a08a4cb7969f7c7109..c83441931caf1fcc3a79c0062014833db3d141b5 100644 --- a/skeletons/per_support.c +++ b/skeletons/per_support.c @@ -18,6 +18,9 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) { if(nbits < 0 || pd->nboff + nbits > pd->nbits) return -1; + ASN_DEBUG("[PER get %d bits from %p+%d bits]", + nbits, pd->buffer, pd->nboff); + /* * Normalize position indicator. */ @@ -190,6 +193,9 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { if(obits <= 0 || obits >= 32) return obits ? -1 : 0; + ASN_DEBUG("[PER put %d bits to %p+%d bits]", + obits, po->buffer, po->nboff); + /* * Normalize position indicator. */