Unverified Commit 1adb32d8 authored by Mouse's avatar Mouse Committed by GitHub

Merge pull request #157 from CedricRouxEurecom/aper-nsnnwn-fixes

APER: fix non negative normally small whole numbers
parents 82ed3517 ee6458b2
...@@ -64,7 +64,7 @@ NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -64,7 +64,7 @@ NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
*/ */
/* XXX handle indefinite index length > 64k */ /* XXX handle indefinite index length > 64k */
value = aper_get_nsnnwn(pd, 65537); value = aper_get_nsnnwn(pd);
if(value < 0) ASN__DECODE_STARVED; if(value < 0) ASN__DECODE_STARVED;
value += specs->extension - 1; value += specs->extension - 1;
//if(value >= specs->map_count) //if(value >= specs->map_count)
...@@ -148,9 +148,7 @@ NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td, ...@@ -148,9 +148,7 @@ NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld", ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
value, specs->extension, inext, value, specs->extension, inext,
value - (inext ? (specs->extension - 1) : 0)); value - (inext ? (specs->extension - 1) : 0));
if(aper_put_nsnnwn(po, if(aper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
ct->upper_bound - ct->lower_bound + 1,
value - (inext ? (specs->extension - 1) : 0)))
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er); ASN__ENCODED_OK(er);
......
...@@ -179,7 +179,6 @@ OCTET_STRING_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -179,7 +179,6 @@ OCTET_STRING_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
raw_len = aper_get_length(pd, csiz->lower_bound, csiz->upper_bound, raw_len = aper_get_length(pd, csiz->lower_bound, csiz->upper_bound,
csiz->effective_bits, &repeat); csiz->effective_bits, &repeat);
if(raw_len < 0) RETURN(RC_WMORE); if(raw_len < 0) RETURN(RC_WMORE);
raw_len += csiz->lower_bound;
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)", ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
(long)csiz->effective_bits, (long)raw_len, (long)csiz->effective_bits, (long)raw_len,
......
...@@ -25,8 +25,7 @@ aper_get_length(asn_per_data_t *pd, ssize_t lb, ssize_t ub, ...@@ -25,8 +25,7 @@ aper_get_length(asn_per_data_t *pd, ssize_t lb, ssize_t ub,
*repeat = 0; *repeat = 0;
if (constrained && ub < 65536) { if (constrained && ub < 65536) {
int range = ub - lb + 1; return aper_get_constrained_whole_number(pd, lb, ub);
return aper_get_nsnnwn(pd, range);
} }
if (aper_get_align(pd) < 0) if (aper_get_align(pd) < 0)
...@@ -70,55 +69,117 @@ aper_get_nslength(asn_per_data_t *pd) { ...@@ -70,55 +69,117 @@ aper_get_nslength(asn_per_data_t *pd) {
} }
ssize_t ssize_t
aper_get_nsnnwn(asn_per_data_t *pd, int range) { aper_get_nsnnwn(asn_per_data_t *pd) {
ssize_t value; int b;
int bytes = 0; int length;
ASN_DEBUG("getting nsnnwn with range %d", range); ASN_DEBUG("getting nsnnwn");
if(range <= 255) { b = per_get_few_bits(pd, 1);
int i; if (b == -1)
return -1;
/* X.691 2002 10.6.1 */
if (b == 0)
return per_get_few_bits(pd, 6);
if (aper_get_align(pd) < 0)
return -1;
/* X.691 2002 10.6.2 */
/* X.691 2002 10.9.3.5 */
b = per_get_few_bits(pd, 1);
if (b == -1)
return -1;
if (b == 1) {
/* other 10.9.3.x cases not handled, it's doubtful we reach them in practice */
ASN_DEBUG("todo: X.691 2002 10.9.3.x");
return -1;
}
/* X.691 2002 10.9.3.6 */
length = per_get_few_bits(pd, 7);
if (length > 4) {
/* todo */
ASN_DEBUG("todo: X.691 2002 10.9.3.6 for length > 4");
return -1;
}
ASN_DEBUG("length %d\n", length);
/* todo: 0xffffffff will be seen as -1 and will lead to decoding failure */
return per_get_few_bits(pd, length * 8);
}
if (range < 0) return -1; /* X.691 2002 10.5 - Decoding of a constrained whole number */
/* 1 -> 8 bits */ long
for (i = 1; i <= 8; i++) { aper_get_constrained_whole_number(asn_per_data_t *pd, long lb, long ub) {
int upper = 1 << i; assert(ub >= lb);
if (upper >= range) long range = ub - lb + 1;
int range_len;
int value_len;
long value;
ASN_DEBUG("aper get constrained_whole_number with lb %ld and ub %ld", lb, ub);
/* X.691 2002 10.5.4 */
if (range == 1)
return lb;
/* X.691 2002 10.5.7.1 - The bit-field case. */
if (range <= 255) {
int bitfield_size = 8;
for (bitfield_size = 8; bitfield_size >= 2; bitfield_size--)
if ((range - 1) & (1 << (bitfield_size-1)))
break; break;
value = per_get_few_bits(pd, bitfield_size);
if (value < 0 || value >= range)
return -1;
return value + lb;
} }
value = per_get_few_bits(pd, i);
return value;
} else if (range == 256){
/* 1 byte */
bytes = 1;
} else if (range <= 65536) {
/* 2 bytes */
bytes = 2;
} else {
//return -1;
int length;
/* handle indefinite range */ /* X.691 2002 10.5.7.2 - The one-octet case. */
length = per_get_few_bits(pd, 1); if (range == 256) {
if (length == 0) if (aper_get_align(pd))
return per_get_few_bits(pd, 6); return -1;
value = per_get_few_bits(pd, 8);
if (value < 0 || value >= range)
return -1;
return value + lb;
}
if (aper_get_align(pd) < 0) /* X.691 2002 10.5.7.3 - The two-octet case. */
if (range <= 65536) {
if (aper_get_align(pd))
return -1; return -1;
value = per_get_few_bits(pd, 16);
if (value < 0 || value >= range)
return -1;
return value + lb;
}
length = per_get_few_bits(pd, 8); /* X.691 2002 10.5.7.4 - The indefinite length case. */
/* the length is not likely to be that big */ /* since we limit input to be 'long' we don't handle all numbers */
if (length > 4) /* and so length determinant is retrieved as X.691 2002 10.9.3.3 */
/* number of bytes to store the range */
for (range_len = 3; ; range_len++) {
long bits = ((long)1) << (8 * range_len);
if (range - 1 < bits)
break;
}
value_len = aper_get_constrained_whole_number(pd, 1, range_len);
if (value_len == -1)
return -1; return -1;
value = 0; if (value_len > 4) {
if (per_get_many_bits(pd, (uint8_t *)&value, 0, length * 8) < 0) ASN_DEBUG("todo: aper_get_constrained_whole_number: value_len > 4");
return -1; return -1;
return value;
} }
if (aper_get_align(pd) < 0) if (aper_get_align(pd))
return -1; return -1;
value = per_get_few_bits(pd, 8 * bytes); value = per_get_few_bits(pd, value_len * 8);
return value; if (value < 0 || value >= range)
return -1;
return value + lb;
} }
int aper_put_align(asn_per_outp_t *po) { int aper_put_align(asn_per_outp_t *po) {
...@@ -142,11 +203,9 @@ aper_put_length(asn_per_outp_t *po, ssize_t lb, ssize_t ub, size_t n, int *need_ ...@@ -142,11 +203,9 @@ aper_put_length(asn_per_outp_t *po, ssize_t lb, ssize_t ub, size_t n, int *need_
ASN_DEBUG("APER put length %zu with range (%zd..%zd)", n, lb, ub); ASN_DEBUG("APER put length %zu with range (%zd..%zd)", n, lb, ub);
/* 11.9 X.691 Note 2 */ /* X.691 2002 10.9.3.3 */
if (constrained && ub < 65536) { if (constrained && ub < 65536)
int range = ub - lb + 1; return aper_put_constrained_whole_number(po, lb, ub, n + lb) ? -1 : (ssize_t)n;
return aper_put_nsnnwn(po, range, n) ? -1 : (ssize_t)n;
}
if (aper_put_align(po) < 0) if (aper_put_align(po) < 0)
return -1; return -1;
...@@ -189,51 +248,113 @@ aper_put_nslength(asn_per_outp_t *po, size_t length) { ...@@ -189,51 +248,113 @@ aper_put_nslength(asn_per_outp_t *po, size_t length) {
} }
int int
aper_put_nsnnwn(asn_per_outp_t *po, int range, int number) { aper_put_nsnnwn(asn_per_outp_t *po, int number) {
int bytes; int len;
ASN_DEBUG("aper put nsnnwn %d", number);
if (number <= 63) {
if (per_put_few_bits(po, 0, 1))
return -1;
return per_put_few_bits(po, number, 6);
}
ASN_DEBUG("aper put nsnnwn %d with range %d", number, range); if (per_put_few_bits(po, 1, 1))
/* 10.5.7.1 X.691 */ return -1;
if(range < 0) {
if (number < 256) {
len = 1;
} else if (number < 65536) {
len = 2;
} else { /* number > 64K */
int i; int i;
for (i = 1; ; i++) { for (i = 3; ; i++) {
int bits = 1 << (8 * i); int bits = 1 << (8 * i);
if (number <= bits) if (number < bits)
break; break;
} }
bytes = i; len = i;
assert(i <= 4);
} }
if(range <= 255) {
int i; if (aper_put_align(po) < 0)
for (i = 1; i <= 8; i++) { return -1;
int bits = 1 << i;
if (range <= bits) /* put the length which is a non-constrained whole number */
if (len <= 127) {
if(per_put_few_bits(po, 0, 1))
return -1;
if(per_put_few_bits(po, len, 7))
return -1;
} else {
/* todo but not big problem, it's very doubtful that the
* number of bytes to encode 'number' will be > 127
*/
return -1;
}
if(aper_put_align(po) < 0) /* Aligning on octet */
return -1;
return per_put_few_bits(po, number, 8 * len);
}
/* X.691 2002 10.5 - Encoding of a constrained whole number */
int
aper_put_constrained_whole_number(asn_per_outp_t *po, long lb, long ub, long number) {
assert(ub >= lb);
long range = ub - lb + 1;
long value = number - lb;
int range_len;
int value_len;
ASN_DEBUG("aper put constrained_whole_number %ld with lb %ld and ub %ld", number, lb, ub);
if (number < lb || number > ub)
return -1;
/* X.691 2002 10.5.4 */
if (range == 1)
return 0;
/* X.691 2002 10.5.7.1 - The bit-field case. */
if (range <= 255) {
int bitfield_size = 8;
for (bitfield_size = 8; bitfield_size >= 2; bitfield_size--)
if ((range - 1) & (1 << (bitfield_size-1)))
break; break;
return per_put_few_bits(po, value, bitfield_size);
} }
return per_put_few_bits(po, number, i);
} else if(range == 256) { /* X.691 2002 10.5.7.2 - The one-octet case. */
if (number >= range) if (range == 256) {
if (aper_put_align(po))
return -1; return -1;
bytes = 1; return per_put_few_bits(po, value, 8);
} else if(range <= 65536) { }
if (number >= range)
/* X.691 2002 10.5.7.3 - The two-octet case. */
if (range <= 65536) {
if (aper_put_align(po))
return -1; return -1;
bytes = 2; return per_put_few_bits(po, value, 16);
} else { /* Ranges > 64K */ }
int i;
for (i = 1; ; i++) { /* X.691 2002 10.5.7.4 - The indefinite length case. */
int bits = 1 << (8 * i); /* since we limit input to be 'long' we don't handle all numbers */
if (range <= bits) /* and so length determinant is stored as X.691 2002 10.9.3.3 */
/* number of bytes to store the range */
for (range_len = 3; ; range_len++) {
int bits = 1 << (8 * range_len);
if (range - 1 < bits)
break; break;
} }
assert(i <= 4); /* number of bytes to store the value */
bytes = i; for (value_len = 1; ; value_len++) {
long bits = ((long)1) << (8 * value_len);
if (value < bits)
break;
} }
if(aper_put_align(po) < 0) /* Aligning on octet */ if (aper_put_constrained_whole_number(po, 1, range_len, value_len))
return -1; return -1;
/* if(per_put_few_bits(po, bytes, 8)) if (aper_put_align(po))
return -1; return -1;
*/ return per_put_few_bits(po, value, value_len * 8);
return per_put_few_bits(po, number, 8 * bytes);
} }
...@@ -27,7 +27,12 @@ ssize_t aper_get_nslength(asn_per_data_t *pd); ...@@ -27,7 +27,12 @@ ssize_t aper_get_nslength(asn_per_data_t *pd);
/* /*
* Get the normally small non-negative whole number. * Get the normally small non-negative whole number.
*/ */
ssize_t aper_get_nsnnwn(asn_per_data_t *pd, int range); ssize_t aper_get_nsnnwn(asn_per_data_t *pd);
/*
* Get the constrained whole number.
*/
long aper_get_constrained_whole_number(asn_per_data_t *po, long lb, long ub);
/* /*
* X.691 (08/2015) #11.9 "General rules for encoding a length determinant" * X.691 (08/2015) #11.9 "General rules for encoding a length determinant"
...@@ -54,7 +59,12 @@ int aper_put_nslength(asn_per_outp_t *po, size_t length); ...@@ -54,7 +59,12 @@ int aper_put_nslength(asn_per_outp_t *po, size_t length);
/* /*
* Put the normally small non-negative whole number. * Put the normally small non-negative whole number.
*/ */
int aper_put_nsnnwn(asn_per_outp_t *po, int range, int number); int aper_put_nsnnwn(asn_per_outp_t *po, int number);
/*
* Put the constrained whole number.
*/
int aper_put_constrained_whole_number(asn_per_outp_t *po, long lb, long ub, long number);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -56,7 +56,7 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -56,7 +56,7 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
if(specs && specs->tag2el_count > specs->ext_start) { if(specs && specs->tag2el_count > specs->ext_start) {
value = aper_get_nsnnwn(pd, specs->tag2el_count - specs->ext_start); /* extension elements range */ value = aper_get_nsnnwn(pd); /* extension elements range */
if(value < 0) ASN__DECODE_STARVED; if(value < 0) ASN__DECODE_STARVED;
value += specs->ext_start; value += specs->ext_start;
if((unsigned)value >= td->elements_count) if((unsigned)value >= td->elements_count)
...@@ -168,7 +168,7 @@ CHOICE_encode_aper(const asn_TYPE_descriptor_t *td, ...@@ -168,7 +168,7 @@ CHOICE_encode_aper(const asn_TYPE_descriptor_t *td,
asn_enc_rval_t rval = {0,0,0}; asn_enc_rval_t rval = {0,0,0};
if(specs->ext_start == -1) if(specs->ext_start == -1)
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
if(aper_put_nsnnwn(po, ct ? ct->range_bits : 0, present - specs->ext_start)) if(aper_put_nsnnwn(po, present - specs->ext_start))
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints, if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints,
memb_ptr, po)) memb_ptr, po))
......
...@@ -129,13 +129,12 @@ SET_OF_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -129,13 +129,12 @@ SET_OF_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
if(value) ct = 0; /* Not restricted! */ if(value) ct = 0; /* Not restricted! */
} }
if(ct && ct->effective_bits >= 0) { if(ct && ct->upper_bound >= 1 && ct->upper_bound <= 65535
&& ct->upper_bound == ct->lower_bound) {
/* X.691, #19.5: No length determinant */ /* X.691, #19.5: No length determinant */
nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound + 1); nelems = ct->upper_bound;
ASN_DEBUG("Preparing to fetch %ld+%lld elements from %s", ASN_DEBUG("Preparing to fetch %ld elements from %s",
(long)nelems, (long long int)ct->lower_bound, td->name); (long)nelems, td->name);
if(nelems < 0) ASN__DECODE_STARVED;
nelems += ct->lower_bound;
} else { } else {
nelems = -1; nelems = -1;
} }
......
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