libFLAC/bitreader.c: Fix undefined behaviour
authorErik de Castro Lopo <erikd@mega-nerd.com>
Sat, 22 Aug 2015 22:05:02 +0000 (08:05 +1000)
committerErik de Castro Lopo <erikd@mega-nerd.com>
Sat, 22 Aug 2015 22:50:33 +0000 (08:50 +1000)
The function FLAC__bitreader_read_raw_int32() triggered undefined behaviour
when sign extending an unsigned value. The Stanford Grahpics bithacks page
provided an alternative that avoided UB.

src/libFLAC/bitreader.c

index f61229b..67d0f37 100644 (file)
@@ -418,12 +418,14 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va
 
 FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, unsigned bits)
 {
+       FLAC__uint32 uval, mask;
        /* OPT: inline raw uint32 code here, or make into a macro if possible in the .h file */
-       if(!FLAC__bitreader_read_raw_uint32(br, (FLAC__uint32*)val, bits))
+       if(!FLAC__bitreader_read_raw_uint32(br, &uval, bits))
                return false;
-       /* sign-extend: */
-       *val <<= (32-bits);
-       *val >>= (32-bits);
+       /* sign-extend *val assuming it is currently bits wide. */
+       /* From: https://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend */
+       mask = 1u << (bits - 1);
+       *val = (uval ^ mask) - mask;
        return true;
 }