Commit 0a8aa604 authored by Lev Walkin's avatar Lev Walkin

per encoding support

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