mirror of https://gerrit.osmocom.org/asn1c
added stack control to PER
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1022 59561ff5-6e30-0410-9f3c-9617f08c8826
This commit is contained in:
parent
68a24641e4
commit
4d2ca1270e
|
@ -19,6 +19,7 @@
|
||||||
#include <errno.h> /* for errno */
|
#include <errno.h> /* for errno */
|
||||||
|
|
||||||
#include <asn_application.h>
|
#include <asn_application.h>
|
||||||
|
#include <asn_internal.h> /* for _ASN_DEFAULT_STACK_MAX */
|
||||||
|
|
||||||
extern asn_TYPE_descriptor_t asn_DEF; /* ASN.1 type to be decoded */
|
extern asn_TYPE_descriptor_t asn_DEF; /* ASN.1 type to be decoded */
|
||||||
#ifdef ASN_PDU_COLLECTION /* Generated by asn1c: -pdu=... */
|
#ifdef ASN_PDU_COLLECTION /* Generated by asn1c: -pdu=... */
|
||||||
|
@ -51,11 +52,17 @@ static enum output_format {
|
||||||
OUT_NULL /* -onull: No pretty-printing */
|
OUT_NULL /* -onull: No pretty-printing */
|
||||||
} oform; /* -o<format> */
|
} oform; /* -o<format> */
|
||||||
|
|
||||||
#define DEBUG(fmt, args...) do { \
|
/* Debug output function */
|
||||||
if(!opt_debug) break; \
|
static inline void
|
||||||
fprintf(stderr, fmt, ##args); \
|
DEBUG(const char *fmt, ...) {
|
||||||
fprintf(stderr, "\n"); \
|
va_list ap;
|
||||||
} while(0)
|
if(!opt_debug) return;
|
||||||
|
fprintf(stderr, "AD: ");
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int ac, char **av) {
|
main(int ac, char **av) {
|
||||||
|
@ -131,9 +138,9 @@ main(int ac, char **av) {
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
opt_stack = atoi(optarg);
|
opt_stack = atoi(optarg);
|
||||||
if(opt_stack <= 0) {
|
if(opt_stack < 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"-s %s: Value greater than 0 expected\n",
|
"-s %s: Non-negative value expected\n",
|
||||||
optarg);
|
optarg);
|
||||||
exit(EX_UNAVAILABLE);
|
exit(EX_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
|
@ -164,8 +171,8 @@ main(int ac, char **av) {
|
||||||
" -c Check ASN.1 constraints after decoding\n"
|
" -c Check ASN.1 constraints after decoding\n"
|
||||||
" -d Enable debugging (-dd is even better)\n"
|
" -d Enable debugging (-dd is even better)\n"
|
||||||
" -n <num> Process files <num> times\n"
|
" -n <num> Process files <num> times\n"
|
||||||
" -s <size> Set the stack usage limit\n"
|
" -s <size> Set the stack usage limit (default is %d)\n"
|
||||||
, (long)suggested_bufsize);
|
, (long)suggested_bufsize, _ASN_DEFAULT_STACK_MAX);
|
||||||
exit(EX_USAGE);
|
exit(EX_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,11 +257,12 @@ static int write_out(const void *buffer, size_t size, void *key) {
|
||||||
return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
|
return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *buffer;
|
static char *buffer;
|
||||||
static size_t buf_offset; /* Offset from the start */
|
|
||||||
static size_t buf_len; /* Length of meaningful contents */
|
static size_t buf_len; /* Length of meaningful contents */
|
||||||
static size_t buf_size; /* Allocated memory */
|
static size_t buf_size; /* Allocated memory */
|
||||||
static off_t buf_shifted; /* Number of bytes ever shifted */
|
static size_t buf_offset; /* Offset from the start */
|
||||||
|
static off_t buf_shifted; /* Number of bytes ever shifted */
|
||||||
|
static int buf_nreallocs; /* Number of reallocations */
|
||||||
|
|
||||||
#define bufptr (buffer + buf_offset)
|
#define bufptr (buffer + buf_offset)
|
||||||
#define bufend (buffer + buf_offset + buf_len)
|
#define bufend (buffer + buf_offset + buf_len)
|
||||||
|
@ -262,13 +270,13 @@ static off_t buf_shifted; /* Number of bytes ever shifted */
|
||||||
/*
|
/*
|
||||||
* Ensure that the buffer contains at least this amount of free space.
|
* Ensure that the buffer contains at least this amount of free space.
|
||||||
*/
|
*/
|
||||||
static void buf_extend(size_t bySize) {
|
static void buf_extend(const void *data2add, size_t bySize) {
|
||||||
|
|
||||||
DEBUG("buf_extend(%ld) { o=%ld l=%ld s=%ld }",
|
DEBUG("buf_extend(%ld) { o=%ld l=%ld s=%ld }",
|
||||||
(long)bySize, (long)buf_offset, (long)buf_len, (long)buf_size);
|
(long)bySize, (long)buf_offset, (long)buf_len, (long)buf_size);
|
||||||
|
|
||||||
if(buf_size >= (buf_offset + buf_len + bySize)) {
|
if(buf_size >= (buf_offset + buf_len + bySize)) {
|
||||||
return; /* Nothing to do */
|
/* Nothing to do */
|
||||||
} else if(bySize <= buf_offset) {
|
} else if(bySize <= buf_offset) {
|
||||||
DEBUG("\tContents shifted by %ld", (long)buf_offset);
|
DEBUG("\tContents shifted by %ld", (long)buf_offset);
|
||||||
|
|
||||||
|
@ -278,17 +286,22 @@ static void buf_extend(size_t bySize) {
|
||||||
buf_offset = 0;
|
buf_offset = 0;
|
||||||
} else {
|
} else {
|
||||||
size_t newsize = (buf_size << 2) + bySize;
|
size_t newsize = (buf_size << 2) + bySize;
|
||||||
void *p = realloc(buffer, newsize);
|
void *p = malloc(newsize);
|
||||||
if(p) {
|
if(!p) {
|
||||||
buffer = (char *)p;
|
|
||||||
buf_size = newsize;
|
|
||||||
|
|
||||||
DEBUG("\tBuffer reallocated to %ld", (long)newsize);
|
|
||||||
} else {
|
|
||||||
perror("realloc()");
|
perror("realloc()");
|
||||||
exit(EX_OSERR);
|
exit(EX_OSERR);
|
||||||
}
|
}
|
||||||
|
memcpy(p, buffer, buf_len);
|
||||||
|
free(buffer);
|
||||||
|
buffer = (char *)p;
|
||||||
|
buf_size = newsize;
|
||||||
|
buf_offset = 0;
|
||||||
|
DEBUG("\tBuffer reallocated to %ld, %d time",
|
||||||
|
(long)newsize, ++buf_nreallocs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(buffer + buf_offset + buf_len, data2add, bySize);
|
||||||
|
buf_len += bySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *fname, ssize_t suggested_bufsize) {
|
static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *fname, ssize_t suggested_bufsize) {
|
||||||
|
@ -310,7 +323,7 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
||||||
DEBUG("Processing file %s", fname);
|
DEBUG("Processing file %s", fname);
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
} else {
|
} else {
|
||||||
DEBUG("Processing standard input");
|
DEBUG("Processing %s", "standard input");
|
||||||
fname = "stdin";
|
fname = "stdin";
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
}
|
}
|
||||||
|
@ -330,8 +343,10 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
||||||
fbuf_size = suggested_bufsize;
|
fbuf_size = suggested_bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf_nreallocs = 0;
|
||||||
buf_shifted = 0;
|
buf_shifted = 0;
|
||||||
buf_offset = 0;
|
buf_offset = 0;
|
||||||
|
buf_size = 0;
|
||||||
buf_len = 0;
|
buf_len = 0;
|
||||||
|
|
||||||
/* Pretend immediate EOF */
|
/* Pretend immediate EOF */
|
||||||
|
@ -339,19 +354,15 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
||||||
rval.consumed = 0;
|
rval.consumed = 0;
|
||||||
|
|
||||||
while((rd = fread(fbuf, 1, fbuf_size, fp)) || !feof(fp)) {
|
while((rd = fread(fbuf, 1, fbuf_size, fp)) || !feof(fp)) {
|
||||||
asn_per_data_t pd;
|
|
||||||
char *i_bptr;
|
char *i_bptr;
|
||||||
size_t i_size;
|
size_t i_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the data over, or use the original buffer.
|
* Copy the data over, or use the original buffer.
|
||||||
*/
|
*/
|
||||||
if(buf_len) {
|
if(buf_size) {
|
||||||
/* Append the new data into the intermediate buffer */
|
/* Append the new data into the intermediate buffer */
|
||||||
buf_extend(rd);
|
buf_extend(fbuf, rd);
|
||||||
memcpy(bufend, fbuf, rd);
|
|
||||||
buf_len += rd;
|
|
||||||
|
|
||||||
i_bptr = bufptr;
|
i_bptr = bufptr;
|
||||||
i_size = buf_len;
|
i_size = buf_len;
|
||||||
} else {
|
} else {
|
||||||
|
@ -369,36 +380,35 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
||||||
(void **)&structure, i_bptr, i_size);
|
(void **)&structure, i_bptr, i_size);
|
||||||
break;
|
break;
|
||||||
case INP_PER:
|
case INP_PER:
|
||||||
pd.buffer = (uint8_t *)i_bptr;
|
rval = uper_decode(opt_codec_ctx, pduType,
|
||||||
pd.nboff = 0;
|
(void **)&structure, i_bptr, i_size);
|
||||||
pd.nbits = i_size * 8;
|
|
||||||
rval = pduType->uper_decoder(opt_codec_ctx, pduType, 0,
|
|
||||||
(void **)&structure, &pd);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DEBUG("decode(%ld) consumed %ld, code %d",
|
DEBUG("decode(%ld) consumed %ld (%ld), code %d",
|
||||||
(long)buf_len, (long)rval.consumed, rval.code);
|
(long)buf_len, (long)rval.consumed, (long)i_size,
|
||||||
|
rval.code);
|
||||||
|
|
||||||
if(buf_len == 0) {
|
if(buf_size == 0) {
|
||||||
/*
|
/*
|
||||||
* Switch the remainder into the intermediate buffer.
|
* Switch the remainder into the intermediate buffer.
|
||||||
*/
|
*/
|
||||||
if(rval.code != RC_FAIL && rval.consumed < rd) {
|
if(rval.code != RC_FAIL && rval.consumed < rd) {
|
||||||
buf_extend(rd - rval.consumed);
|
buf_extend(fbuf + rval.consumed,
|
||||||
memcpy(bufend,
|
rd - rval.consumed);
|
||||||
fbuf + rval.consumed,
|
rval.consumed = 0;
|
||||||
rd - rval.consumed);
|
|
||||||
buf_len = rd - rval.consumed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(rval.code) {
|
switch(rval.code) {
|
||||||
case RC_OK:
|
case RC_OK:
|
||||||
DEBUG("RC_OK, finishing up");
|
DEBUG("RC_OK, finishing up with %ld",
|
||||||
|
(long)rval.consumed);
|
||||||
if(fp != stdin) fclose(fp);
|
if(fp != stdin) fclose(fp);
|
||||||
return structure;
|
return structure;
|
||||||
case RC_WMORE:
|
case RC_WMORE:
|
||||||
DEBUG("RC_WMORE, continuing...");
|
DEBUG("RC_WMORE, continuing %ld with %ld..%ld..%ld",
|
||||||
|
(long)rval.consumed, (long)buf_offset,
|
||||||
|
(long)buf_len, (long)buf_size);
|
||||||
/*
|
/*
|
||||||
* Adjust position inside the source buffer.
|
* Adjust position inside the source buffer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,11 +13,13 @@ extern "C" {
|
||||||
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure defines a context that may be passed to every ASN.1 encoder
|
* This structure defines a set of parameters that may be passed
|
||||||
* or decoder function.
|
* to every ASN.1 encoder or decoder function.
|
||||||
* WARNING: if max_stack_size member is set, and you are calling the
|
* WARNING: if max_stack_size member is set, and you are calling the
|
||||||
* function pointers of the asn_TYPE_descriptor_t directly,
|
* function pointers of the asn_TYPE_descriptor_t directly,
|
||||||
* this structure must be ALLOCATED ON THE STACK!
|
* this structure must be ALLOCATED ON THE STACK!
|
||||||
|
* If you can't always satisfy this requirement, use ber_decode(),
|
||||||
|
* xer_decode() and uper_decode() functions instead.
|
||||||
*/
|
*/
|
||||||
typedef struct asn_codec_ctx_s {
|
typedef struct asn_codec_ctx_s {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -82,6 +82,28 @@ static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
|
||||||
if(cb(" ", 4, app_key) < 0) return -1; \
|
if(cb(" ", 4, app_key) < 0) return -1; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check stack against overflow, if limit is set.
|
||||||
|
*/
|
||||||
|
#define _ASN_DEFAULT_STACK_MAX (30000)
|
||||||
|
static inline int
|
||||||
|
_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
|
||||||
|
if(ctx && ctx->max_stack_size) {
|
||||||
|
|
||||||
|
/* ctx MUST be allocated on the stack */
|
||||||
|
ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx);
|
||||||
|
if(usedstack > 0) usedstack = -usedstack; /* grows up! */
|
||||||
|
|
||||||
|
/* double negative required to avoid int wrap-around */
|
||||||
|
if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
|
||||||
|
ASN_DEBUG("Stack limit %ld reached",
|
||||||
|
(long)ctx->max_stack_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,11 +33,18 @@ ber_decode(asn_codec_ctx_t *opt_codec_ctx,
|
||||||
asn_codec_ctx_t s_codec_ctx;
|
asn_codec_ctx_t s_codec_ctx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Satisfy the requirement that the codec context
|
* Stack checker requires that the codec context
|
||||||
* must be allocated on the stack.
|
* must be allocated on the stack.
|
||||||
*/
|
*/
|
||||||
if(opt_codec_ctx && opt_codec_ctx->max_stack_size) {
|
if(opt_codec_ctx) {
|
||||||
s_codec_ctx = *opt_codec_ctx;
|
if(opt_codec_ctx->max_stack_size) {
|
||||||
|
s_codec_ctx = *opt_codec_ctx;
|
||||||
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* If context is not given, be security-conscious anyway */
|
||||||
|
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
|
||||||
|
s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
|
||||||
opt_codec_ctx = &s_codec_ctx;
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,17 +80,8 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
|
||||||
/*
|
/*
|
||||||
* Make sure we didn't exceed the maximum stack size.
|
* Make sure we didn't exceed the maximum stack size.
|
||||||
*/
|
*/
|
||||||
if(opt_codec_ctx && opt_codec_ctx->max_stack_size) {
|
if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
|
||||||
ptrdiff_t usedstack = ((char *)opt_codec_ctx - (char *)&size);
|
RETURN(RC_FAIL);
|
||||||
/* double negative is required to avoid int wrap-around */
|
|
||||||
if(usedstack > 0) usedstack = -usedstack;
|
|
||||||
ASN_DEBUG("Current stack size %ld", -(long)usedstack);
|
|
||||||
if(usedstack < -(ptrdiff_t)opt_codec_ctx->max_stack_size) {
|
|
||||||
ASN_DEBUG("Stack limit %ld reached",
|
|
||||||
(long)opt_codec_ctx->max_stack_size);
|
|
||||||
RETURN(RC_FAIL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* So what does all this implicit skip stuff mean?
|
* So what does all this implicit skip stuff mean?
|
||||||
|
|
|
@ -46,8 +46,8 @@ typedef asn_dec_rval_t (ber_type_decoder_f)(
|
||||||
* head->last_tag_form is non-zero.
|
* head->last_tag_form is non-zero.
|
||||||
*/
|
*/
|
||||||
asn_dec_rval_t ber_check_tags(
|
asn_dec_rval_t ber_check_tags(
|
||||||
struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */
|
struct asn_codec_ctx_s *opt_codec_ctx, /* codec options */
|
||||||
struct asn_TYPE_descriptor_s *type_dsc,
|
struct asn_TYPE_descriptor_s *type_descriptor,
|
||||||
asn_struct_ctx_t *opt_ctx, /* saved decoding context */
|
asn_struct_ctx_t *opt_ctx, /* saved decoding context */
|
||||||
const void *ptr, size_t size,
|
const void *ptr, size_t size,
|
||||||
int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */
|
int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */
|
||||||
|
|
|
@ -84,17 +84,8 @@ ber_skip_length(asn_codec_ctx_t *opt_codec_ctx,
|
||||||
/*
|
/*
|
||||||
* Make sure we didn't exceed the maximum stack size.
|
* Make sure we didn't exceed the maximum stack size.
|
||||||
*/
|
*/
|
||||||
if(opt_codec_ctx && opt_codec_ctx->max_stack_size) {
|
if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
|
||||||
ptrdiff_t usedstack = ((char *)opt_codec_ctx - (char *)&size);
|
return -1;
|
||||||
/* double negative is required to avoid int wrap-around */
|
|
||||||
if(usedstack > 0) usedstack = -usedstack;
|
|
||||||
ASN_DEBUG("Current stack size %ld", -(long)usedstack);
|
|
||||||
if(usedstack < -(ptrdiff_t)opt_codec_ctx->max_stack_size) {
|
|
||||||
ASN_DEBUG("Stack limit %ld reached",
|
|
||||||
(long)opt_codec_ctx->max_stack_size);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the size of L in TLV.
|
* Determine the size of L in TLV.
|
||||||
|
|
|
@ -31,7 +31,6 @@ ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
|
||||||
* RETURN VALUES:
|
* RETURN VALUES:
|
||||||
* Standard {-1,0,>0} convention.
|
* Standard {-1,0,>0} convention.
|
||||||
*/
|
*/
|
||||||
struct asn_codec_ctx_s; /* Forward declaration */
|
|
||||||
ssize_t ber_skip_length(
|
ssize_t ber_skip_length(
|
||||||
struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */
|
struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */
|
||||||
int _is_constructed, const void *bufptr, size_t size);
|
int _is_constructed, const void *bufptr, size_t size);
|
||||||
|
|
|
@ -827,6 +827,9 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||||
void *st = *sptr;
|
void *st = *sptr;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
|
if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
|
||||||
|
_ASN_DECODE_FAILED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the target structure if it is not present already.
|
* Create the target structure if it is not present already.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -703,7 +703,8 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||||
}
|
}
|
||||||
|
|
||||||
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
|
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
|
||||||
ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d", tcv, ctx->phase);
|
ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
|
||||||
|
tcv, ctx->phase, xml_tag);
|
||||||
|
|
||||||
/* Skip the extensions section */
|
/* Skip the extensions section */
|
||||||
if(ctx->phase == 3) {
|
if(ctx->phase == 3) {
|
||||||
|
@ -829,7 +830,13 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASN_DEBUG("Unexpected XML tag in SEQUENCE");
|
ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
|
||||||
|
size>0?((const char *)buf_ptr)[0]:'.',
|
||||||
|
size>1?((const char *)buf_ptr)[1]:'.',
|
||||||
|
size>2?((const char *)buf_ptr)[2]:'.',
|
||||||
|
size>3?((const char *)buf_ptr)[3]:'.',
|
||||||
|
size>4?((const char *)buf_ptr)[4]:'.',
|
||||||
|
size>5?((const char *)buf_ptr)[5]:'.');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,6 +1035,9 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||||
|
|
||||||
(void)constraints;
|
(void)constraints;
|
||||||
|
|
||||||
|
if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
|
||||||
|
_ASN_DECODE_FAILED;
|
||||||
|
|
||||||
if(!st) {
|
if(!st) {
|
||||||
st = *sptr = CALLOC(1, specs->struct_size);
|
st = *sptr = CALLOC(1, specs->struct_size);
|
||||||
if(!st) _ASN_DECODE_FAILED;
|
if(!st) _ASN_DECODE_FAILED;
|
||||||
|
|
|
@ -864,6 +864,9 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||||
int repeat = 0;
|
int repeat = 0;
|
||||||
ssize_t nelems;
|
ssize_t nelems;
|
||||||
|
|
||||||
|
if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
|
||||||
|
_ASN_DECODE_FAILED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the target structure if it is not present already.
|
* Create the target structure if it is not present already.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,2 +1,38 @@
|
||||||
#include <asn_application.h>
|
#include <asn_application.h>
|
||||||
|
#include <asn_internal.h>
|
||||||
#include <per_decoder.h>
|
#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) {
|
||||||
|
asn_codec_ctx_t s_codec_ctx;
|
||||||
|
asn_per_data_t pd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stack checker requires that the codec context
|
||||||
|
* must be allocated on the stack.
|
||||||
|
*/
|
||||||
|
if(opt_codec_ctx) {
|
||||||
|
if(opt_codec_ctx->max_stack_size) {
|
||||||
|
s_codec_ctx = *opt_codec_ctx;
|
||||||
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* If context is not given, be security-conscious anyway */
|
||||||
|
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
|
||||||
|
s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
|
||||||
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill in the position indicator */
|
||||||
|
pd.buffer = (const uint8_t *)buffer;
|
||||||
|
pd.nboff = 0;
|
||||||
|
pd.nbits = 8 * size; /* 8 is CHAR_BIT from <limits.h> */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invoke type-specific decoder.
|
||||||
|
*/
|
||||||
|
if(!td->uper_decoder)
|
||||||
|
_ASN_DECODE_FAILED; /* PER is not compiled in */
|
||||||
|
return td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,18 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unaligned PER decoder of any ASN.1 type. May be invoked by the application.
|
||||||
|
*/
|
||||||
|
asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
|
||||||
|
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
|
||||||
|
void **struct_ptr, /* Pointer to a target structure's pointer */
|
||||||
|
const void *buffer, /* Data to be decoded */
|
||||||
|
size_t size /* Size of data buffer */
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pre-computed PER constraints.
|
* Pre-computed PER constraints.
|
||||||
|
@ -23,7 +35,6 @@ extern "C" {
|
||||||
APC_EXTENSIBLE = 0x4 /* May have extension */
|
APC_EXTENSIBLE = 0x4 /* May have extension */
|
||||||
};
|
};
|
||||||
typedef struct asn_per_constraint_s {
|
typedef struct asn_per_constraint_s {
|
||||||
|
|
||||||
enum asn_per_constraint_flags flags;
|
enum asn_per_constraint_flags flags;
|
||||||
int range_bits; /* Full number of bits in the range */
|
int range_bits; /* Full number of bits in the range */
|
||||||
int effective_bits; /* Effective bits */
|
int effective_bits; /* Effective bits */
|
||||||
|
@ -35,9 +46,6 @@ typedef struct asn_per_constraints_s {
|
||||||
asn_per_constraint_t size;
|
asn_per_constraint_t size;
|
||||||
} asn_per_constraints_t;
|
} asn_per_constraints_t;
|
||||||
|
|
||||||
|
|
||||||
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Type of the type-specific PER decoder function.
|
* Type of the type-specific PER decoder function.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,7 +12,7 @@ int32_t
|
||||||
per_get_few_bits(asn_per_data_t *pd, int nbits) {
|
per_get_few_bits(asn_per_data_t *pd, int nbits) {
|
||||||
size_t off; /* Next after last bit offset */
|
size_t off; /* Next after last bit offset */
|
||||||
uint32_t accum;
|
uint32_t accum;
|
||||||
uint8_t *buf;
|
const uint8_t *buf;
|
||||||
|
|
||||||
if(nbits < 0 || pd->nboff + nbits > pd->nbits)
|
if(nbits < 0 || pd->nboff + nbits > pd->nbits)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -15,9 +15,9 @@ extern "C" {
|
||||||
* This structure describes a position inside a PER bit stream.
|
* This structure describes a position inside a PER bit stream.
|
||||||
*/
|
*/
|
||||||
typedef struct asn_per_data_s {
|
typedef struct asn_per_data_s {
|
||||||
uint8_t *buffer; /* Pointer to the octet stream */
|
const uint8_t *buffer; /* Pointer to the octet stream */
|
||||||
size_t nboff; /* Bit offset to the meaningful bit */
|
size_t nboff; /* Bit offset to the meaningful bit */
|
||||||
size_t nbits; /* Number of bits in the stream */
|
size_t nbits; /* Number of bits in the stream */
|
||||||
} asn_per_data_t;
|
} asn_per_data_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -16,11 +16,18 @@ xer_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||||
asn_codec_ctx_t s_codec_ctx;
|
asn_codec_ctx_t s_codec_ctx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Satisfy the requirement that the codec context
|
* Stack checker requires that the codec context
|
||||||
* must be allocated on the stack.
|
* must be allocated on the stack.
|
||||||
*/
|
*/
|
||||||
if(opt_codec_ctx && opt_codec_ctx->max_stack_size) {
|
if(opt_codec_ctx) {
|
||||||
s_codec_ctx = *opt_codec_ctx;
|
if(opt_codec_ctx->max_stack_size) {
|
||||||
|
s_codec_ctx = *opt_codec_ctx;
|
||||||
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* If context is not given, be security-conscious anyway */
|
||||||
|
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
|
||||||
|
s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
|
||||||
opt_codec_ctx = &s_codec_ctx;
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ extern "C" {
|
||||||
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The XER decoder of any type. May be invoked by the application.
|
* The XER decoder of any ASN.1 type. May be invoked by the application.
|
||||||
*/
|
*/
|
||||||
asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx,
|
asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx,
|
||||||
struct asn_TYPE_descriptor_s *type_descriptor,
|
struct asn_TYPE_descriptor_s *type_descriptor,
|
||||||
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 that buffer */
|
size_t size /* Size of data buffer */
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue