aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libbsc/rest_octets.c
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2016-12-14 14:51:40 +0100
committerHarald Welte <laforge@gnumonks.org>2017-01-23 12:32:00 +0000
commit881064e9b81de4aee7a9cdd52184860260f8723c (patch)
tree8c6655af403554274bd7a0486e888deda6329303 /openbsc/src/libbsc/rest_octets.c
parent47e178190744e65079a821f40148eebcaa92bf76 (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.c21
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);
}