Commit d14802fa authored by Lev Walkin's avatar Lev Walkin

fix OER SEQUENCE decode memory leak

parent 9d328eec
...@@ -7,6 +7,32 @@ ...@@ -7,6 +7,32 @@
#include <asn_internal.h> #include <asn_internal.h>
#include <asn_bit_data.h> #include <asn_bit_data.h>
/*
* 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 * char *
asn_bit_data_string(asn_bit_data_t *pd) { asn_bit_data_string(asn_bit_data_t *pd) {
static char buf[2][32]; static char buf[2][32];
......
...@@ -23,6 +23,12 @@ typedef struct asn_bit_data_s { ...@@ -23,6 +23,12 @@ typedef struct asn_bit_data_s {
void *refill_key; void *refill_key;
} asn_bit_data_t; } 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. * 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 * This function returns -1 if the specified number of bits could not be
......
...@@ -107,12 +107,6 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -107,12 +107,6 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
* Restore parsing context. * Restore parsing context.
*/ */
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); 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. * Start to parse where left previously.
...@@ -122,11 +116,10 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -122,11 +116,10 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
/* /*
* Fetch preamble. * Fetch preamble.
*/ */
asn_bit_data_t *preamble = ctx->ptr; asn_bit_data_t *preamble;
int has_extensions_bit = (specs->ext_before >= 0); int has_extensions_bit = (specs->ext_before >= 0);
size_t preamble_bits = (has_extensions_bit + specs->roms_count); size_t preamble_bits = (has_extensions_bit + specs->roms_count);
size_t preamble_bytes = ((7 + preamble_bits) >> 3); size_t preamble_bytes = ((7 + preamble_bits) >> 3);
uint8_t *pbytes;
ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name); 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, ...@@ -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)", "Expecting preamble bits %zu for %s (including %d extension bits)",
preamble_bits, td->name, has_extensions_bit); preamble_bits, td->name, has_extensions_bit);
if(size < preamble_bytes) { if(preamble_bytes > size) {
ASN__DECODE_STARVED; ASN__DECODE_STARVED;
} }
pbytes = MALLOC(preamble_bytes + 1); preamble = asn_bit_data_new_contiguous(ptr, preamble_bits);
if(!pbytes) { if(!preamble) {
RETURN(RC_FAIL); 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->nboff = has_extensions_bit;
preamble->nbits = preamble_bits; ctx->ptr = preamble;
ADVANCE(preamble_bytes); ADVANCE(preamble_bytes);
} }
NEXT_PHASE(ctx); NEXT_PHASE(ctx);
...@@ -158,6 +148,8 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_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); ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
assert(preamble);
for(edx = (ctx->step >> 1); edx < td->elements_count; for(edx = (ctx->step >> 1); edx < td->elements_count;
edx++, ctx->step = (ctx->step & ~1) + 2) { edx++, ctx->step = (ctx->step & ~1) + 2) {
asn_TYPE_member_t *elm = &td->elements[edx]; asn_TYPE_member_t *elm = &td->elements[edx];
...@@ -231,7 +223,9 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -231,7 +223,9 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
} }
NEXT_PHASE(ctx); NEXT_PHASE(ctx);
/* FALL THROUGH */ /* FALL THROUGH */
case 2: { case 2:
assert(ctx->ptr);
{
/* Cleanup preamble. */ /* Cleanup preamble. */
asn_bit_data_t *preamble = ctx->ptr; asn_bit_data_t *preamble = ctx->ptr;
asn_bit_data_t *extadds; asn_bit_data_t *extadds;
...@@ -243,17 +237,9 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -243,17 +237,9 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
uint8_t unused_bits; uint8_t unused_bits;
size_t len = 0; size_t len = 0;
ssize_t len_len; 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); 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. */ preamble->buffer = 0; /* Will do extensions_present==1 next time. */
if(!extensions_present) { if(!extensions_present) {
...@@ -291,19 +277,12 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -291,19 +277,12 @@ SEQUENCE_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
} }
/* Get the extensions map */ /* Get the extensions map */
ebytes = MALLOC(len + 1); extadds = asn_bit_data_new_contiguous(ptr, len * 8 - unused_bits);
if(!ebytes) { if(!extadds) {
RETURN(RC_FAIL); RETURN(RC_FAIL);
} }
memcpy(ebytes, ptr, len); FREEMEM(preamble);
ebytes[len] = '\0'; ctx->ptr = extadds;
extadds = preamble;
memset(extadds, 0, sizeof(*extadds));
extadds->buffer = ebytes;
extadds->nboff = 0;
extadds->nbits = 8 * len - unused_bits;
ADVANCE(len); ADVANCE(len);
} }
NEXT_PHASE(ctx); NEXT_PHASE(ctx);
......
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