libFLAC/bitreader.c: Fix shift invoking undefined behaviour
authorErik de Castro Lopo <erikd@mega-nerd.com>
Mon, 18 Nov 2019 08:02:31 +0000 (19:02 +1100)
committerErik de Castro Lopo <erikd@mega-nerd.com>
Mon, 18 Nov 2019 19:10:19 +0000 (06:10 +1100)
Credit: Oss-Fuzz
Issue: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18535
Testcase: fuzzer_decoder-6573800707063808

src/libFLAC/bitreader.c

index d2c058d..3fdb12b 100644 (file)
@@ -403,18 +403,19 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va
                        /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */
                        const uint32_t n = FLAC__BITS_PER_WORD - br->consumed_bits;
                        const brword word = br->buffer[br->consumed_words];
+                       const brword mask = br->consumed_bits < FLAC__BITS_PER_WORD ? FLAC__WORD_ALL_ONES >> br->consumed_bits : 0;
                        if(bits < n) {
-                               *val = (FLAC__uint32)((word & (FLAC__WORD_ALL_ONES >> br->consumed_bits)) >> (n-bits)); /* The result has <= 32 non-zero bits */
+                               *val = (FLAC__uint32)((word & mask) >> (n-bits)); /* The result has <= 32 non-zero bits */
                                br->consumed_bits += bits;
                                return true;
                        }
                        /* (FLAC__BITS_PER_WORD - br->consumed_bits <= bits) ==> (FLAC__WORD_ALL_ONES >> br->consumed_bits) has no more than 'bits' non-zero bits */
-                       *val = (FLAC__uint32)(word & (FLAC__WORD_ALL_ONES >> br->consumed_bits));
+                       *val = (FLAC__uint32)(word & mask);
                        bits -= n;
                        br->consumed_words++;
                        br->consumed_bits = 0;
                        if(bits) { /* if there are still bits left to read, there have to be less than 32 so they will all be in the next word */
-                               *val <<= bits;
+                               *val = bits >= 32 ? 0 : *val << bits ;
                                *val |= (FLAC__uint32)(br->buffer[br->consumed_words] >> (FLAC__BITS_PER_WORD-bits));
                                br->consumed_bits = bits;
                        }