summaryrefslogtreecommitdiff
path: root/jbig2dec
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2020-03-27 05:41:07 +0800
committerSebastian Rasmussen <sebras@gmail.com>2020-04-03 04:15:41 +0800
commitdc6b8098b52db7e1a9b20c1ef6f1006555c04b1b (patch)
treeabdd25f7008181e25ef73ddac94ea09bd1de8c47 /jbig2dec
parentf14f35c6e3218554cd351b848447cfa83b3c4256 (diff)
downloadghostpdl-dc6b8098b52db7e1a9b20c1ef6f1006555c04b1b.tar.gz
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.
Diffstat (limited to 'jbig2dec')
-rw-r--r--jbig2dec/jbig2_mmr.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/jbig2dec/jbig2_mmr.c b/jbig2dec/jbig2_mmr.c
index 8029c8139..94ff429ba 100644
--- a/jbig2dec/jbig2_mmr.c
+++ b/jbig2dec/jbig2_mmr.c
@@ -45,6 +45,7 @@ typedef struct {
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 @@ typedef struct {
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_halftone_mmr(Jbig2Ctx *ctx, const Jbig2GenericRegionParams *params,
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;
}