From dc6b8098b52db7e1a9b20c1ef6f1006555c04b1b Mon Sep 17 00:00:00 2001
From: Sebastian Rasmussen <sebras@gmail.com>
Date: Fri, 27 Mar 2020 05:41:07 +0800
Subject: [PATCH] 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.
---
 jbig2dec/jbig2_mmr.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/jbig2dec/jbig2_mmr.c b/jbig2dec/jbig2_mmr.c
index 8029c81..94ff429 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;
 }
-- 
1.8.3.1

