ref: dc14b5a69be02341d84e2956131f93f962408af2
parent: 0665a13dcda6ab99dd93c1002d52e0206c7ecb0b
author: Sebastian Rasmussen <sebras@gmail.com>
date: Fri Mar 27 01:41:07 EDT 2020
jbig2dec: Adjust number of bytes consumed by MMR decoder. The MMR decoder pre-buffers up to 32 bits of encoded input data in a word buffer before they are consumed by the MMR decoder. Once bits are consumed, the pre-buffer will be filled up with more input data. When filling up the buffer the decoder would previously stay clear of reading data belonging to succeeding segments, but still indicated that it consumed those bytes it never read. Once finished the MMR decoder lied to the caller by propagating the incorrect number of consumed bytes. The caller subtracted the consumed number of bytes from the size and end up in underflow causing the next MMR decoding to first read input data at the wrong location, later ending up attempting to read outside the MMR encoded input buffer. Now, the MMR decoder keeps track of how many bits it has consumed and accurately rounds this number up to a whole number of bytes to the caller. Fixes OSS-fuzz issue 17855. Thanks to OSS-fuzz for reporting.
--- a/jbig2_mmr.c
+++ b/jbig2_mmr.c
@@ -45,6 +45,7 @@
uint32_t height;
const byte *data;
size_t size;
+ size_t consumed_bits;
uint32_t data_index;
uint32_t bit_index;
uint32_t word;
@@ -58,30 +59,34 @@
static void
jbig2_decode_mmr_init(Jbig2MmrCtx *mmr, int width, int height, const byte *data, size_t size)
{
- size_t i;
- uint32_t word = 0;
-
mmr->width = width;
mmr->height = height;
mmr->data = data;
mmr->size = size;
mmr->data_index = 0;
- mmr->bit_index = 0;
+ mmr->bit_index = 32;
+ mmr->word = 0;
+ mmr->consumed_bits = 0;
- for (i = 0; i < size && i < 4; i++)
- word |= (data[i] << ((3 - i) << 3));
- mmr->word = word;
+ while (mmr->bit_index >= 8 && mmr->data_index < mmr->size) {
+ mmr->bit_index -= 8;
+ mmr->word |= (mmr->data[mmr->data_index] << mmr->bit_index);
+ mmr->data_index++;
+ }
}
static void
jbig2_decode_mmr_consume(Jbig2MmrCtx *mmr, int n_bits)
{
+ mmr->consumed_bits += n_bits;
+ if (mmr->consumed_bits > mmr->size * 8)
+ mmr->consumed_bits = mmr->size * 8;
+
mmr->word <<= n_bits;
mmr->bit_index += n_bits;
- while (mmr->bit_index >= 8) {
+ while (mmr->bit_index >= 8 && mmr->data_index < mmr->size) {
mmr->bit_index -= 8;
- if (mmr->data_index + 4 < mmr->size)
- mmr->word |= (mmr->data[mmr->data_index + 4] << mmr->bit_index);
+ mmr->word |= (mmr->data[mmr->data_index] << mmr->bit_index);
mmr->data_index++;
}
}
@@ -1259,6 +1264,6 @@
jbig2_decode_mmr_consume(&mmr, 24);
}
- *consumed_bytes += mmr.data_index + (mmr.bit_index >> 3) + (mmr.bit_index > 0 ? 1 : 0);
+ *consumed_bytes += (mmr.consumed_bits + 7) / 8;
return code;
}