diff options
author | Max <msuraev@sysmocom.de> | 2016-12-14 14:51:40 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2017-01-23 12:32:00 +0000 |
commit | 881064e9b81de4aee7a9cdd52184860260f8723c (patch) | |
tree | 8c6655af403554274bd7a0486e888deda6329303 /openbsc/src/libbsc/rest_octets.c | |
parent | 47e178190744e65079a821f40148eebcaa92bf76 (diff) |
Prevent segfault in range encoding
* Explicitly check when ARFCN array split is impossible and return
gracefully instead of using negative index.
* Separate range encoding into generic function and use it for all
SI-related things.
* Propagate the error into that function and to its callers.
* Add separate test-case for the segfault previously triggered by this bug.
Change-Id: I3e049ab2d7c1c4d6c791b148f37e10636a8e43e0
Related: RT#7379
Diffstat (limited to 'openbsc/src/libbsc/rest_octets.c')
-rw-r--r-- | openbsc/src/libbsc/rest_octets.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 1a5e43525..fc0282e06 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -180,10 +180,10 @@ static inline void append_earfcn(struct bitvec *bv, bitvec_set_bit(bv, L); } -static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, +static inline int append_uarfcn(struct bitvec *bv, const uint16_t *u, const uint16_t *sc, size_t length) { - int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length]; + int f0_inc, i, w[RANGE_ENC_MAX_ARFCNS] = { 0 }, a[length]; uint8_t chan_list[16] = {0}; /* 3G Neighbour Cell Description */ @@ -211,9 +211,9 @@ static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, /* Note: we do not support multiple UARFCN values ATM: */ bitvec_set_uint(bv, u[0], 14); - arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc); - range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0); - range_enc_range1024(chan_list, 0, f0_inc, w); + f0_inc = range_encode(ARFCN_RANGE_1024, a, length, w, 0, chan_list); + if (f0_inc < 0) + return f0_inc; /* FDD_Indic0: parameter value '0000000000' is not a member of the set */ bitvec_set_bit(bv, f0_inc); @@ -229,12 +229,15 @@ static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, /* UTRAN TDD Description */ bitvec_set_bit(bv, 0); + + return 0; } /* generate SI2quater rest octets: 3GPP TS 44.018 ยง 10.5.2.33b */ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, const uint16_t *u, const uint16_t *sc, size_t u_len) { + int rc; unsigned sz; struct bitvec bv; bv.data = data; @@ -279,7 +282,13 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, SI2Q_MAX_LEN); return -ENOMEM; } - append_uarfcn(&bv, u, sc, u_len); + rc = append_uarfcn(&bv, u, sc, u_len); + if (rc < 0) { + LOGP(DRR, LOGL_ERROR, "SI2quater: failed to append %zu " + "UARFCNs due to range encoding failure: %s\n", + u_len, strerror(-rc)); + return rc; + } } else { /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); } |