diff --git a/skeletons/asn_bit_data.c b/skeletons/asn_bit_data.c index e7021f4c..056e8f37 100644 --- a/skeletons/asn_bit_data.c +++ b/skeletons/asn_bit_data.c @@ -7,6 +7,32 @@ #include #include +/* + * Create a contiguous non-refillable bit data structure. + * Can be freed by FREEMEM(). + */ +asn_bit_data_t * +asn_bit_data_new_contiguous(const void *data, size_t size_bits) { + size_t size_bytes = (size_bits + 7) / 8; + asn_bit_data_t *pd; + uint8_t *bytes; + + /* Get the extensions map */ + pd = CALLOC(1, sizeof(*pd) + size_bytes + 1); + if(!pd) { + return NULL; + } + bytes = (void *)(((char *)pd) + sizeof(*pd)); + memcpy(bytes, data, size_bytes); + bytes[size_bytes] = 0; + pd->buffer = bytes; + pd->nboff = 0; + pd->nbits = size_bits; + + return pd; +} + + char * asn_bit_data_string(asn_bit_data_t *pd) { static char buf[2][32]; diff --git a/skeletons/asn_bit_data.h b/skeletons/asn_bit_data.h index 8b136631..59de7af5 100644 --- a/skeletons/asn_bit_data.h +++ b/skeletons/asn_bit_data.h @@ -23,6 +23,12 @@ typedef struct asn_bit_data_s { void *refill_key; } asn_bit_data_t; +/* + * Create a contiguous non-refillable bit data structure. + * Can be freed by FREEMEM(). + */ +asn_bit_data_t *asn_bit_data_new_contiguous(const void *data, size_t size_bits); + /* * Extract a small number of bits (<= 31) from the specified PER data pointer. * This function returns -1 if the specified number of bits could not be diff --git a/skeletons/constr_SEQUENCE_oer.c b/skeletons/constr_SEQUENCE_oer.c index 43bd11ab..6138f1a3 100644 --- a/skeletons/constr_SEQUENCE_oer.c +++ b/skeletons/constr_SEQUENCE_oer.c @@ -107,12 +107,6 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, * Restore parsing context. */ ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); - if(ctx->ptr == 0) { - ctx->ptr = CALLOC(1, sizeof(asn_bit_data_t)); - if(!ctx->ptr) { - RETURN(RC_FAIL); - } - } /* * Start to parse where left previously. @@ -122,11 +116,10 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, /* * Fetch preamble. */ - asn_bit_data_t *preamble = ctx->ptr; + asn_bit_data_t *preamble; int has_extensions_bit = (specs->ext_before >= 0); size_t preamble_bits = (has_extensions_bit + specs->roms_count); size_t preamble_bytes = ((7 + preamble_bits) >> 3); - uint8_t *pbytes; ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name); @@ -134,19 +127,16 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, "Expecting preamble bits %zu for %s (including %d extension bits)", preamble_bits, td->name, has_extensions_bit); - if(size < preamble_bytes) { + if(preamble_bytes > size) { ASN__DECODE_STARVED; } - pbytes = MALLOC(preamble_bytes + 1); - if(!pbytes) { + preamble = asn_bit_data_new_contiguous(ptr, preamble_bits); + if(!preamble) { RETURN(RC_FAIL); } - preamble->buffer = (const void *)pbytes; - memcpy(pbytes, ptr, preamble_bytes); - pbytes[preamble_bytes] = '\0'; /* Just in case */ preamble->nboff = has_extensions_bit; - preamble->nbits = preamble_bits; + ctx->ptr = preamble; ADVANCE(preamble_bytes); } NEXT_PHASE(ctx); @@ -158,6 +148,8 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name); + assert(preamble); + for(edx = (ctx->step >> 1); edx < td->elements_count; edx++, ctx->step = (ctx->step & ~1) + 2) { asn_TYPE_member_t *elm = &td->elements[edx]; @@ -231,7 +223,9 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, } NEXT_PHASE(ctx); /* FALL THROUGH */ - case 2: { + case 2: + assert(ctx->ptr); + { /* Cleanup preamble. */ asn_bit_data_t *preamble = ctx->ptr; asn_bit_data_t *extadds; @@ -243,17 +237,9 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, uint8_t unused_bits; size_t len = 0; ssize_t len_len; - uint8_t *ebytes; - - union { - const uint8_t *cptr; - uint8_t *uptr; - } unconst; ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name); - unconst.cptr = preamble->buffer; - FREEMEM(unconst.uptr); preamble->buffer = 0; /* Will do extensions_present==1 next time. */ if(!extensions_present) { @@ -291,19 +277,12 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, } /* Get the extensions map */ - ebytes = MALLOC(len + 1); - if(!ebytes) { + extadds = asn_bit_data_new_contiguous(ptr, len * 8 - unused_bits); + if(!extadds) { RETURN(RC_FAIL); } - memcpy(ebytes, ptr, len); - ebytes[len] = '\0'; - - extadds = preamble; - memset(extadds, 0, sizeof(*extadds)); - extadds->buffer = ebytes; - extadds->nboff = 0; - extadds->nbits = 8 * len - unused_bits; - + FREEMEM(preamble); + ctx->ptr = extadds; ADVANCE(len); } NEXT_PHASE(ctx);