From cf37c4cd293def64ca87a82def0be2c8aab12cf0 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 21 Jan 2016 16:52:40 +0100 Subject: Fix sporadic out-of-bounds error This code dealing with bit shifting sometimes gets 1 byte beyond array boundary while calculating index. This is now explicitly checked and prevented. Ticket: OW#1198 Sponsored-by: On-Waves ehf --- src/gsm/gsm_utils.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index fad59bc1..e8e452f8 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -129,13 +129,11 @@ uint8_t gsm_get_octet_len(const uint8_t sept_len){ /* GSM 03.38 6.2.1 Character unpacking */ int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind) { - int i = 0; - int shift = 0; - uint8_t c7, c8; - uint8_t next_is_ext = 0; + unsigned shift = 0; + uint8_t c7, c8, next_is_ext = 0, lu, ru; + const uint8_t maxlen = gsm_get_octet_len(septet_l); const char *text_buf_begin = text; const char *text_buf_end = text + n; - int nchars; OSMO_ASSERT (n > 0); @@ -148,12 +146,24 @@ int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_ septet_l = septet_l - shift; } + unsigned i, l, r; for (i = 0; i < septet_l && text != text_buf_end - 1; i++) { - c7 = - ((user_data[((i + shift) * 7 + 7) >> 3] << - (7 - (((i + shift) * 7 + 7) & 7))) | - (user_data[((i + shift) * 7) >> 3] >> - (((i + shift) * 7) & 7))) & 0x7f; + + l = ((i + shift) * 7 + 7) >> 3; + r = ((i + shift) * 7) >> 3; + + /* the left side index is always >= right side index + sometimes it even gets beyond array boundary + check for that explicitly and force 0 instead + */ + if (l >= maxlen) + lu = 0; + else + lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7)); + + ru = user_data[r] >> (((i + shift) * 7) & 7); + + c7 = (lu | ru) & 0x7f; if (next_is_ext) { /* this is an extension character */ @@ -169,11 +179,9 @@ int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_ *(text++) = c8; } - nchars = text - text_buf_begin; - *text = '\0'; - return nchars; + return text - text_buf_begin; } int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l) -- cgit v1.2.3