aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm/gsm_utils.c
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2016-01-21 16:52:40 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-01-22 23:08:12 +0100
commitcf37c4cd293def64ca87a82def0be2c8aab12cf0 (patch)
treeed7dc1eda140596c69012b5328ddec836200afda /src/gsm/gsm_utils.c
parentfb7e6835758d378be9e09a60a98c3fce405f61d2 (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/gsm/gsm_utils.c')
-rw-r--r--src/gsm/gsm_utils.c34
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)