diff options
author | Max <msuraev@sysmocom.de> | 2016-01-21 16:52:40 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2016-01-22 23:08:12 +0100 |
commit | cf37c4cd293def64ca87a82def0be2c8aab12cf0 (patch) | |
tree | ed7dc1eda140596c69012b5328ddec836200afda /src | |
parent | fb7e6835758d378be9e09a60a98c3fce405f61d2 (diff) |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/gsm/gsm_utils.c | 34 |
1 files 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) |