Unverified Commit 51735138 authored by Mouse's avatar Mouse Committed by GitHub

Merge pull request #54 from riebl/per_intmax

per_support: use intmax_t for integer constraints
parents 92d2802c 16207b15
...@@ -636,11 +636,11 @@ INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -636,11 +636,11 @@ INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
/* #11.5.6 */ /* #11.5.6 */
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) {
if((size_t)ct->range_bits > 8 * sizeof(unsigned long)) if((size_t)ct->range_bits > 8 * sizeof(uintmax_t))
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
if(specs && specs->field_unsigned) { if(specs && specs->field_unsigned) {
unsigned long uvalue = 0; uintmax_t uvalue = 0;
if(uper_get_constrained_whole_number(pd, if(uper_get_constrained_whole_number(pd,
&uvalue, ct->range_bits)) &uvalue, ct->range_bits))
ASN__DECODE_STARVED; ASN__DECODE_STARVED;
...@@ -650,16 +650,16 @@ INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx, ...@@ -650,16 +650,16 @@ INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
if(asn_ulong2INTEGER(st, uvalue)) if(asn_ulong2INTEGER(st, uvalue))
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
} else { } else {
unsigned long uvalue = 0; uintmax_t uvalue = 0;
long svalue; intmax_t svalue;
if(uper_get_constrained_whole_number(pd, if(uper_get_constrained_whole_number(pd,
&uvalue, ct->range_bits)) &uvalue, ct->range_bits))
ASN__DECODE_STARVED; ASN__DECODE_STARVED;
ASN_DEBUG("Got value %lu + low %ld", ASN_DEBUG("Got value %lu + low %ld",
uvalue, ct->lower_bound); uvalue, ct->lower_bound);
if(per_long_range_unrebase(uvalue, ct->lower_bound, if(per_imax_range_unrebase(uvalue, ct->lower_bound,
ct->upper_bound, &svalue) ct->upper_bound, &svalue)
|| asn_long2INTEGER(st, svalue)) { || asn_imax2INTEGER(st, svalue)) {
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
} }
} }
...@@ -715,7 +715,7 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td, ...@@ -715,7 +715,7 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
const uint8_t *buf; const uint8_t *buf;
const uint8_t *end; const uint8_t *end;
const asn_per_constraint_t *ct; const asn_per_constraint_t *ct;
long value = 0; intmax_t value = 0;
if(!st || st->size == 0) ASN__ENCODE_FAILED; if(!st || st->size == 0) ASN__ENCODE_FAILED;
...@@ -727,16 +727,16 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td, ...@@ -727,16 +727,16 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
if(ct) { if(ct) {
int inext = 0; int inext = 0;
if(specs && specs->field_unsigned) { if(specs && specs->field_unsigned) {
unsigned long uval; uintmax_t uval;
if(asn_INTEGER2ulong(st, &uval)) if(asn_INTEGER2umax(st, &uval))
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
/* Check proper range */ /* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) { if(ct->flags & APC_SEMI_CONSTRAINED) {
if(uval < (unsigned long)ct->lower_bound) if(uval < (uintmax_t)ct->lower_bound)
inext = 1; inext = 1;
} else if(ct->range_bits >= 0) { } else if(ct->range_bits >= 0) {
if(uval < (unsigned long)ct->lower_bound if(uval < (uintmax_t)ct->lower_bound
|| uval > (unsigned long)ct->upper_bound) || uval > (uintmax_t)ct->upper_bound)
inext = 1; inext = 1;
} }
ASN_DEBUG("Value %lu (%02x/%" ASN_PRI_SIZE ") lb %lu ub %lu %s", ASN_DEBUG("Value %lu (%02x/%" ASN_PRI_SIZE ") lb %lu ub %lu %s",
...@@ -745,7 +745,7 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td, ...@@ -745,7 +745,7 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
inext ? "ext" : "fix"); inext ? "ext" : "fix");
value = uval; value = uval;
} else { } else {
if(asn_INTEGER2long(st, &value)) if(asn_INTEGER2imax(st, &value))
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
/* Check proper range */ /* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) { if(ct->flags & APC_SEMI_CONSTRAINED) {
...@@ -773,22 +773,22 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td, ...@@ -773,22 +773,22 @@ INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
/* X.691-11/2008, #13.2.2, test if constrained whole number */ /* X.691-11/2008, #13.2.2, test if constrained whole number */
if(ct && ct->range_bits >= 0) { if(ct && ct->range_bits >= 0) {
unsigned long v; uintmax_t v;
/* #11.5.6 -> #11.3 */ /* #11.5.6 -> #11.3 */
ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits", ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
value, value - ct->lower_bound, ct->range_bits); value, value - ct->lower_bound, ct->range_bits);
if(specs && specs->field_unsigned) { if(specs && specs->field_unsigned) {
if ( ((unsigned long)ct->lower_bound > (unsigned long)(ct->upper_bound) if ( ((uintmax_t)ct->lower_bound > (uintmax_t)(ct->upper_bound)
|| ((unsigned long)value < (unsigned long)ct->lower_bound)) || ((uintmax_t)value < (uintmax_t)ct->lower_bound))
|| ((unsigned long)value > (unsigned long)ct->upper_bound) || ((uintmax_t)value > (uintmax_t)ct->upper_bound)
) { ) {
ASN_DEBUG("Value %lu to-be-encoded is outside the bounds [%lu, %lu]!", ASN_DEBUG("Value %lu to-be-encoded is outside the bounds [%lu, %lu]!",
value, ct->lower_bound, ct->upper_bound); value, ct->lower_bound, ct->upper_bound);
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
v = (unsigned long)value - (unsigned long)ct->lower_bound; v = (uintmax_t)value - (uintmax_t)ct->lower_bound;
} else { } else {
if(per_long_range_rebase(value, ct->lower_bound, ct->upper_bound, &v)) { if(per_imax_range_rebase(value, ct->lower_bound, ct->upper_bound, &v)) {
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
} }
......
...@@ -121,9 +121,9 @@ uper_put_nsnnwn(asn_per_outp_t *po, int n) { ...@@ -121,9 +121,9 @@ uper_put_nsnnwn(asn_per_outp_t *po, int n) {
/* X.691-2008/11, #11.5.6 -> #11.3 */ /* X.691-2008/11, #11.5.6 -> #11.3 */
int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_value, int nbits) { int uper_get_constrained_whole_number(asn_per_data_t *pd, uintmax_t *out_value, int nbits) {
unsigned long lhalf; /* Lower half of the number*/ uintmax_t lhalf; /* Lower half of the number*/
long half; intmax_t half;
if(nbits <= 31) { if(nbits <= 31) {
half = per_get_few_bits(pd, nbits); half = per_get_few_bits(pd, nbits);
...@@ -141,7 +141,7 @@ int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_val ...@@ -141,7 +141,7 @@ int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_val
if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31)) if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31))
return -1; return -1;
*out_value = ((unsigned long)half << (nbits - 31)) | lhalf; *out_value = ((uintmax_t)half << (nbits - 31)) | lhalf;
return 0; return 0;
} }
...@@ -216,13 +216,13 @@ uper_put_nslength(asn_per_outp_t *po, size_t length) { ...@@ -216,13 +216,13 @@ uper_put_nslength(asn_per_outp_t *po, size_t length) {
} }
static int static int
per__long_range(long lb, long ub, unsigned long *range_r) { per__imax_range(intmax_t lb, intmax_t ub, uintmax_t *range_r) {
unsigned long bounds_range; uintmax_t bounds_range;
if((ub < 0) == (lb < 0)) { if((ub < 0) == (lb < 0)) {
bounds_range = ub - lb; bounds_range = ub - lb;
} else if(lb < 0) { } else if(lb < 0) {
assert(ub >= 0); assert(ub >= 0);
bounds_range = 1 + ((unsigned long)ub + (unsigned long)-(lb + 1)); bounds_range = 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1));
} else { } else {
assert(!"Unreachable"); assert(!"Unreachable");
return -1; return -1;
...@@ -232,12 +232,12 @@ per__long_range(long lb, long ub, unsigned long *range_r) { ...@@ -232,12 +232,12 @@ per__long_range(long lb, long ub, unsigned long *range_r) {
} }
int int
per_long_range_rebase(long v, long lb, long ub, unsigned long *output) { per_imax_range_rebase(intmax_t v, intmax_t lb, intmax_t ub, uintmax_t *output) {
unsigned long range; uintmax_t range;
assert(lb <= ub); assert(lb <= ub);
if(v < lb || v > ub || per__long_range(lb, ub, &range) < 0) { if(v < lb || v > ub || per__imax_range(lb, ub, &range) < 0) {
/* Range error. */ /* Range error. */
return -1; return -1;
} }
...@@ -253,12 +253,12 @@ per_long_range_rebase(long v, long lb, long ub, unsigned long *output) { ...@@ -253,12 +253,12 @@ per_long_range_rebase(long v, long lb, long ub, unsigned long *output) {
*output = v-lb; *output = v-lb;
return 0; return 0;
} else if(v < 0) { } else if(v < 0) {
unsigned long rebased = 1 + (unsigned long)-(v+1) + (unsigned long)lb; uintmax_t rebased = 1 + (uintmax_t)-(v+1) + (uintmax_t)lb;
assert(rebased <= range); /* By construction */ assert(rebased <= range); /* By construction */
*output = rebased; *output = rebased;
return 0; return 0;
} else if(lb < 0) { } else if(lb < 0) {
unsigned long rebased = 1 + (unsigned long)-(lb+1) + (unsigned long)v; uintmax_t rebased = 1 + (uintmax_t)-(lb+1) + (uintmax_t)v;
assert(rebased <= range); /* By construction */ assert(rebased <= range); /* By construction */
*output = rebased; *output = rebased;
return 0; return 0;
...@@ -269,10 +269,18 @@ per_long_range_rebase(long v, long lb, long ub, unsigned long *output) { ...@@ -269,10 +269,18 @@ per_long_range_rebase(long v, long lb, long ub, unsigned long *output) {
} }
int int
per_long_range_unrebase(unsigned long inp, long lb, long ub, long *outp) { per_long_range_rebase(long v, intmax_t lb, intmax_t ub, unsigned long *output) {
unsigned long range; uintmax_t tmp = *output;
int rc = per_imax_range_rebase((intmax_t)v, lb, ub, &tmp);
*output = tmp;
return rc;
}
int
per_imax_range_unrebase(uintmax_t inp, intmax_t lb, intmax_t ub, intmax_t *outp) {
uintmax_t range;
if(per__long_range(lb, ub, &range) != 0) { if(per__imax_range(lb, ub, &range) != 0) {
return -1; return -1;
} }
...@@ -285,15 +293,23 @@ per_long_range_unrebase(unsigned long inp, long lb, long ub, long *outp) { ...@@ -285,15 +293,23 @@ per_long_range_unrebase(unsigned long inp, long lb, long ub, long *outp) {
return -1; return -1;
} }
if(inp <= LONG_MAX) { if(inp <= INTMAX_MAX) {
*outp = (long)inp + lb; *outp = (long)inp + lb;
} else { } else {
*outp = (lb + LONG_MAX + 1) + (long)((inp - LONG_MAX) - 1); *outp = (lb + INTMAX_MAX + 1) + (intmax_t)((inp - INTMAX_MAX) - 1);
} }
return 0; return 0;
} }
int
per_long_range_unrebase(unsigned long inp, intmax_t lb, intmax_t ub, long *outp) {
intmax_t tmp = *outp;
int rc = per_imax_range_unrebase((uintmax_t)inp, lb, ub, &tmp);
*outp = tmp;
return rc;
}
int32_t int32_t
aper_get_align(asn_per_data_t *pd) { aper_get_align(asn_per_data_t *pd) {
......
...@@ -24,8 +24,8 @@ typedef struct asn_per_constraint_s { ...@@ -24,8 +24,8 @@ typedef struct asn_per_constraint_s {
} 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 */
long lower_bound; /* "lb" value */ intmax_t lower_bound; /* "lb" value */
long upper_bound; /* "ub" value */ intmax_t upper_bound; /* "ub" value */
} asn_per_constraint_t; } asn_per_constraint_t;
typedef struct asn_per_constraints_s { typedef struct asn_per_constraints_s {
asn_per_constraint_t value; asn_per_constraint_t value;
...@@ -64,7 +64,7 @@ ssize_t uper_get_nsnnwn(asn_per_data_t *pd); ...@@ -64,7 +64,7 @@ ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
ssize_t aper_get_nsnnwn(asn_per_data_t *pd, int range); ssize_t aper_get_nsnnwn(asn_per_data_t *pd, int range);
/* X.691-2008/11, #11.5.6 */ /* X.691-2008/11, #11.5.6 */
int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits); int uper_get_constrained_whole_number(asn_per_data_t *pd, uintmax_t *v, int nbits);
/* Temporary compatibility layer. Will get removed. */ /* Temporary compatibility layer. Will get removed. */
...@@ -81,9 +81,11 @@ typedef struct asn_bit_outp_s asn_per_outp_t; ...@@ -81,9 +81,11 @@ typedef struct asn_bit_outp_s asn_per_outp_t;
* -1: Conversion failed due to range problems. * -1: Conversion failed due to range problems.
* 0: Conversion was successful. * 0: Conversion was successful.
*/ */
int per_long_range_rebase(long v, long lb, long ub, unsigned long *output); int per_long_range_rebase(long, intmax_t lb, intmax_t ub, unsigned long *output);
int per_imax_range_rebase(intmax_t v, intmax_t lb, intmax_t ub, uintmax_t *output);
/* The inverse operation: restores the value by the offset and its bounds. */ /* The inverse operation: restores the value by the offset and its bounds. */
int per_long_range_unrebase(unsigned long inp, long lb, long ub, long *outp); int per_long_range_unrebase(unsigned long inp, intmax_t lb, intmax_t ub, long *outp);
int per_imax_range_unrebase(uintmax_t inp, intmax_t lb, intmax_t ub, intmax_t *outp);
/* X.691-2008/11, #11.5 */ /* X.691-2008/11, #11.5 */
int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits); int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits);
......
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