From 1b38a280d97c9c3b705d1e3d9f62ba5c4468c3dd Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 1 May 2016 01:02:17 +0200 Subject: aper fix for decoding constrained integer with lower boundary When decoding a constrained integer with a lower boundary, we need to make sure the lower bound is added after decoding the raw offset inside the range. Before this change, RANAP_CauseMisc_unspecified_failure (115) would be encoded as 2 (115 - 113 = 2), but would be decoded as 2, rather than 113+2 = 115. Code for this was taken from openairinterface5g/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0 which unfortunately doesn't carry much of a revision history :/ --- skeletons/INTEGER.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'skeletons') diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index eef89f58..b3f0da12 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -716,34 +716,43 @@ INTEGER_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ASN_DEBUG("Integer with range %d bits", ct->range_bits); if(ct->range_bits >= 0) { if (ct->range_bits > 16) { - int max_range_bytes = (ct->range_bits >> 3) + 1; - int length, i; + int max_range_bytes = (ct->range_bits >> 3) + + (((ct->range_bits % 8) > 0) ? 1 : 0); + int length = 0, i; int64_t value = 0; - for (i = 0; i < max_range_bytes; i++) { - int upper = 1 << (i + 1); - if (upper > max_range_bytes) + for (i = 1; ; i++) { + int upper = 1 << i; + if (upper >= max_range_bytes) break; } - if ((length = per_get_few_bits(pd, i + 1)) < 0) - _ASN_DECODE_STARVED; + ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits, + max_range_bytes, i); + + if ((length = per_get_few_bits(pd, i)) < 0) + _ASN_DECODE_FAILED; + + /* X.691 #12.2.6 length determinant + lb (1) */ + length += 1; + ASN_DEBUG("Got length %d", length); + if (aper_get_align(pd) != 0) _ASN_DECODE_STARVED; - ASN_DEBUG("Got length %d", length + 1); - for (i = 0; i < length + 1; i++) { + + while (length--) { int buf = per_get_few_bits(pd, 8); if (buf < 0) _ASN_DECODE_STARVED; - value += (((int64_t)buf) << (8 * i)); + value += (((int64_t)buf) << (8 * length)); } + value += ct->lower_bound; if((specs && specs->field_unsigned) ? asn_uint642INTEGER(st, value) : asn_int642INTEGER(st, value)) _ASN_DECODE_FAILED; ASN_DEBUG("Got value %lld + low %lld", value, ct->lower_bound); - value += ct->lower_bound; } else { long value = 0; if (ct->range_bits < 8) { @@ -761,13 +770,13 @@ INTEGER_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, value = per_get_few_bits(pd, 16); if(value < 0) _ASN_DECODE_STARVED; } + value += ct->lower_bound; if((specs && specs->field_unsigned) ? asn_ulong2INTEGER(st, value) : asn_long2INTEGER(st, value)) _ASN_DECODE_FAILED; ASN_DEBUG("Got value %ld + low %lld", value, ct->lower_bound); - value += ct->lower_bound; } return rval; } else { -- cgit v1.2.3