Address sanitizer complains with a buffer overflow to the end of
gsm_fr_map:

ERROR: AddressSanitizer: global-buffer-overflow on address 0x00000044f76c at pc 
0x43c0dd bp 0x7fff18389db0 sp 0x7fff18389da8
READ of size 1 at 0x00000044f76c thread T0
    #0 0x43c0dc in trau_encode_fr 
/home/alphaone/scm/osmo/openbsc/openbsc/src/libtrau/trau_mux.c:441
    #1 0x42fad6 in test_trau_fr_efr 
/home/alphaone/scm/osmo/openbsc/openbsc/tests/trau/trau_test.c:35
    #2 0x4308f4 in main 
/home/alphaone/scm/osmo/openbsc/openbsc/tests/trau/trau_test.c:70
    #3 0x7f96e8cf04bc (/lib64/libc.so.6+0x224bc)
    #4 0x42f7ec 
(/home/alphaone/scm/osmo/openbsc/openbsc/tests/trau/trau_test+0x42f7ec)
0x00000044f76c is located 52 bytes to the left of global variable 
'c_bits_check_fr' from 'trau_mux.c' (0x44f7a0) of size 5
0x00000044f76c is located 0 bytes to the right of global variable 'gsm_fr_map' 
from 'trau_mux.c' (0x44f720) of size 76
SUMMARY: AddressSanitizer: global-buffer-overflow 
/home/alphaone/scm/osmo/openbsc/openbsc/src/libtrau/trau_mux.c:441 
trau_encode_fr

In the last iteration of the loop k is already set to the next element
in gsm_fr_map which leads to an out-of-bounds read. Instead decrement k
at the end of the loop and put the check before the data assignment.
This is functionally equivalent as k is never < 0 initially.

This happens in trau_decode_fr as well.
---
 openbsc/src/libtrau/trau_mux.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c
index 4f159e4..9b93eda 100644
--- a/openbsc/src/libtrau/trau_mux.c
+++ b/openbsc/src/libtrau/trau_mux.c
@@ -234,13 +234,14 @@ struct msgb *trau_decode_fr(uint32_t callref,
        l = 0; /* counts element bits */
        o = 0; /* offset input bits */
        while (i < 260) {
-               data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
-               if (--k < 0) {
+               if (k < 0) {
                        o += gsm_fr_map[l];
                        k = gsm_fr_map[++l]-1;
                }
+               data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
                i++;
                j++;
+               k--;
        }
        frame->msg_type = GSM_TCHF_FRAME;
        frame->callref = callref;
@@ -435,16 +436,14 @@ void trau_encode_fr(struct decoded_trau_frame *tf,
        l = 0; /* counts element bits */
        o = 0; /* offset output bits */
        while (i < 260) {
-               tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
-               /* to avoid out-of-bounds access in gsm_fr_map[++l] */
-               if (i == 259)
-                       break;
-               if (--k < 0) {
+               if (k < 0) {
                        o += gsm_fr_map[l];
                        k = gsm_fr_map[++l]-1;
                }
+               tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
                i++;
                j++;
+               k--;
        }
 }
 
-- 
1.8.4.2


Reply via email to