shithub: jbig2

Download patch

ref: 346a90f18c4592dc6cbcf53f007105a4273505eb
parent: 873694419b3498708b90c5c36ee0a73795a90c84
author: Sebastian Rasmussen <sebras@gmail.com>
date: Sun Sep 15 13:58:40 EDT 2019

jbig2dec: Let arithmetic decoder and the underlying stream report errors.

When a called function indicates an error, the caller should print warnings.
Since the arithmetic decoder now uses the normal way of reporting errors,
the callers of the decoder are changed to report warnings.

--- a/jbig2.c
+++ b/jbig2.c
@@ -461,14 +461,15 @@
 } Jbig2WordStreamBuf;
 
 static int
-jbig2_word_stream_buf_get_next_word(Jbig2WordStream *self, size_t offset, uint32_t *word)
+jbig2_word_stream_buf_get_next_word(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word)
 {
     Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *) self;
     uint32_t val = 0;
     int ret = 0;
 
-    if (self == NULL || word == NULL)
-        return -1;
+    if (self == NULL || word == NULL) {
+        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to read next word of stream because stream or output missing");
+    }
     if (offset >= z->size) {
         *word = 0;
         return 0;
--- a/jbig2_arith.c
+++ b/jbig2_arith.c
@@ -53,8 +53,8 @@
   invitation to bitrot.
 */
 
-static void
-jbig2_arith_bytein(Jbig2ArithState *as)
+static int
+jbig2_arith_bytein(Jbig2Ctx *ctx, Jbig2ArithState *as)
 {
     int new_bytes;
     byte B;
@@ -86,7 +86,10 @@
         if (as->next_word_bytes == 1) {
             Jbig2WordStream *ws = as->ws;
 
-            new_bytes = ws->get_next_word(ws, as->offset, &as->next_word);
+            new_bytes = ws->get_next_word(ctx, ws, as->offset, &as->next_word);
+            if (new_bytes < 0) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read from underlying stream during arithmetic decoding");
+            }
             as->next_word_bytes = new_bytes;
             as->offset += new_bytes;
 
@@ -134,7 +137,10 @@
         if (as->next_word_bytes == 0) {
             Jbig2WordStream *ws = as->ws;
 
-            new_bytes = ws->get_next_word(ws, as->offset, &as->next_word);
+            new_bytes = ws->get_next_word(ctx, ws, as->offset, &as->next_word);
+            if (new_bytes < 0) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read from underlying stream during arithmetic decoding");
+            }
             as->offset += new_bytes;
             as->next_word_bytes = new_bytes;
         }
@@ -141,6 +147,8 @@
         B = (byte)((as->next_word >> 24) & 0xFF);
         as->C += 0xFF00 - (B << 8);
     }
+
+    return 0;
 }
 
 /** Allocate and initialize a new arithmetic coding state
@@ -161,7 +169,12 @@
 
     result->ws = ws;
 
-    new_bytes = ws->get_next_word(ws, 0, &result->next_word);
+    new_bytes = ws->get_next_word(ctx, ws, 0, &result->next_word);
+    if (new_bytes < 0) {
+        jbig2_free(ctx->allocator, result);
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to initialize underlying stream of arithmetic decoder");
+        return NULL;
+    }
     result->next_word_bytes = new_bytes;
     result->offset = new_bytes;
 
@@ -168,7 +181,14 @@
     /* Figure F.1 */
     result->C = (~(result->next_word >> 8)) & 0xFF0000;
 
-    jbig2_arith_bytein(result);
+    /* Figure E.20 (2) */
+    if (jbig2_arith_bytein(ctx, result) < 0) {
+        jbig2_free(ctx->allocator, result);
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read second byte from underlying stream when initializing arithmetic decoder");
+        return NULL;
+    }
+
+    /* Figure E.20 (3) */
     result->C <<= 7;
     result->CT -= 7;
     result->A = 0x8000;
@@ -235,21 +255,24 @@
     {0x5601, 46 ^ 46, 46 ^ 46}
 };
 
-static void
-jbig2_arith_renormd(Jbig2ArithState *as)
+static int
+jbig2_arith_renormd(Jbig2Ctx *ctx, Jbig2ArithState *as)
 {
     /* Figure E.18 */
     do {
-        if (as->CT == 0)
-            jbig2_arith_bytein(as);
+        if (as->CT == 0 && jbig2_arith_bytein(ctx, as) < 0) {
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read byte from compressed data stream");
+        }
         as->A <<= 1;
         as->C <<= 1;
         as->CT--;
     } while ((as->A & 0x8000) == 0);
+
+    return 0;
 }
 
 int
-jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx)
+jbig2_arith_decode(Jbig2Ctx *ctx, Jbig2ArithState *as, Jbig2ArithCx *pcx)
 {
     Jbig2ArithCx cx = *pcx;
     const Jbig2ArithQe *pqe;
@@ -256,8 +279,9 @@
     unsigned int index = cx & 0x7f;
     bool D;
 
-    if (index >= MAX_QE_ARRAY_SIZE)
-        return -1; /* Error */
+    if (index >= MAX_QE_ARRAY_SIZE) {
+        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to determine probability estimate because index out of range");
+    }
 
     pqe = &jbig2_arith_Qe[index];
 
@@ -273,7 +297,10 @@
                 D = cx >> 7;
                 *pcx ^= pqe->mps_xor;
             }
-            jbig2_arith_renormd(as);
+            if (jbig2_arith_renormd(ctx, as) < 0) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to renormalize decoder");
+            }
+
             return D;
         } else {
             return cx >> 7;
@@ -290,7 +317,10 @@
             D = 1 - (cx >> 7);
             *pcx ^= pqe->lps_xor;
         }
-        jbig2_arith_renormd(as);
+        if (jbig2_arith_renormd(ctx, as) < 0) {
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to renormalize decoder");
+        }
+
         return D;
     }
 }
@@ -313,7 +343,7 @@
 #endif
 
 static int
-test_get_word(Jbig2WordStream *self, size_t offset, uint32_t *word)
+test_get_word(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word)
 {
     uint32_t val = 0;
     int ret = 0;
@@ -362,11 +392,11 @@
 
     for (i = 0; i < 256; i++) {
 #ifdef JBIG2_DEBUG_ARITH
-        bool D =
+        int D =
 #else
         (void)
 #endif
-            jbig2_arith_decode(as, &cx);
+            jbig2_arith_decode(ctx, as, &cx);
 
 #ifdef JBIG2_DEBUG_ARITH
         fprintf(stderr, "%3d: D = %d, ", i, D);
--- a/jbig2_arith.h
+++ b/jbig2_arith.h
@@ -32,7 +32,7 @@
 
 /* decode a bit */
 /* Normally returns 0 or 1. May return negative in case of error. */
-int jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx);
+int jbig2_arith_decode(Jbig2Ctx *ctx, Jbig2ArithState *as, Jbig2ArithCx *pcx);
 
 /* returns true if the end of the data stream has been reached (for sanity checks) */
 bool jbig2_arith_has_reached_marker(Jbig2ArithState *as);
--- a/jbig2_arith_iaid.c
+++ b/jbig2_arith_iaid.c
@@ -79,9 +79,9 @@
 
     /* A.3 (2) */
     for (i = 0; i < SBSYMCODELEN; i++) {
-        D = jbig2_arith_decode(as, &IAIDx[PREV]);
+        D = jbig2_arith_decode(ctx, as, &IAIDx[PREV]);
         if (D < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAIDx code");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAIDx code");
 #ifdef VERBOSE
         fprintf(stderr, "IAID%x: D = %d\n", PREV, D);
 #endif
--- a/jbig2_arith_int.c
+++ b/jbig2_arith_int.c
@@ -64,37 +64,37 @@
     int n_tail, offset;
     int i;
 
-    S = jbig2_arith_decode(as, &IAx[PREV]);
+    S = jbig2_arith_decode(ctx, as, &IAx[PREV]);
     if (S < 0)
-        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx S");
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx S");
     PREV = (PREV << 1) | S;
 
-    bit = jbig2_arith_decode(as, &IAx[PREV]);
+    bit = jbig2_arith_decode(ctx, as, &IAx[PREV]);
     if (bit < 0)
-        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 0");
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx decision bit 0");
     PREV = (PREV << 1) | bit;
     if (bit) {
-        bit = jbig2_arith_decode(as, &IAx[PREV]);
+        bit = jbig2_arith_decode(ctx, as, &IAx[PREV]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 1");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx decision bit 1");
         PREV = (PREV << 1) | bit;
 
         if (bit) {
-            bit = jbig2_arith_decode(as, &IAx[PREV]);
+            bit = jbig2_arith_decode(ctx, as, &IAx[PREV]);
             if (bit < 0)
-                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 2");
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx decision bit 2");
             PREV = (PREV << 1) | bit;
 
             if (bit) {
-                bit = jbig2_arith_decode(as, &IAx[PREV]);
+                bit = jbig2_arith_decode(ctx, as, &IAx[PREV]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 3");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx decision bit 3");
                 PREV = (PREV << 1) | bit;
 
                 if (bit) {
-                    bit = jbig2_arith_decode(as, &IAx[PREV]);
+                    bit = jbig2_arith_decode(ctx, as, &IAx[PREV]);
                     if (bit < 0)
-                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 4");
+                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx decision bit 4");
                     PREV = (PREV << 1) | bit;
 
                     if (bit) {
@@ -123,9 +123,9 @@
 
     V = 0;
     for (i = 0; i < n_tail; i++) {
-        bit = jbig2_arith_decode(as, &IAx[PREV]);
+        bit = jbig2_arith_decode(ctx, as, &IAx[PREV]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx V bit %d", i);
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode IAx V bit %d", i);
         PREV = ((PREV << 1) & 511) | (PREV & 256) | bit;
         V = (V << 1) | bit;
     }
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -408,9 +408,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 optimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit | ((line_m1 >> (7 - x_minor)) & 0x10) | ((line_m2 >> (7 - x_minor)) & 0x800);
             }
@@ -477,9 +477,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
                 CONTEXT |= (ppd>>2) & 0x7000; /* Next 3 pixels */
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 unoptimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 unoptimized");
             }
             pd = pd<<1;
             ppd = ppd<<1;
@@ -543,9 +543,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
                 CONTEXT |= (pd>>9) & 0x01F0; /* Next 5 pixels */
                 CONTEXT |= (ppd>>4) & 0x1E00; /* Next 4 pixels */
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 unoptimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 unoptimized");
             }
             pd = pd<<1;
             ppd = ppd<<1;
@@ -614,9 +614,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 optimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0xefb) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x8) | ((line_m2 >> (8 - x_minor)) & 0x200);
             }
@@ -674,9 +674,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
                 CONTEXT |= (pd>>11) & 0x078; /* Next 4 pixels */
                 CONTEXT |= (ppd>>7) & 0x380; /* Next 3 pixels */
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 unoptimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 unoptimized");
             }
             pd = pd<<1;
             ppd = ppd<<1;
@@ -746,9 +746,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 optimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
             }
@@ -805,9 +805,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 optimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x10);
             }
@@ -856,9 +856,9 @@
                 CONTEXT  = out_byte & 0x00F; /* First 4 pixels */
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
                 CONTEXT |= (pd>>9) & 0x3E0; /* Next 5 pixels */
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 unoptimized");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 unoptimized");
             }
             pd = pd<<1;
             out_byte = (out_byte<<1) | bit;
@@ -921,9 +921,9 @@
         params->gbat[6] == -2 && params->gbat[7] == -2)
     {
         for (y = 0; y < GBH; y++) {
-            int bit = jbig2_arith_decode(as, &GB_stats[0x9B25]);
+            int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x9B25]);
             if (bit < 0)
-                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
             LTP ^= bit;
             if (!LTP) {
                 uint32_t out_byte = 0;
@@ -950,9 +950,9 @@
                         CONTEXT  = out_byte & 0x00F; /* First 4 pixels */
                         CONTEXT |= (pd>>8) & 0x7F0; /* Next 7 pixels */
                         CONTEXT |= (ppd>>2) & 0xF800; /* Final 5 pixels */
-                        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                        bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                         if (bit < 0)
-                            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
+                            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
                     }
                     pd = pd<<1;
                     ppd = ppd<<1;
@@ -1019,9 +1019,9 @@
     /* So 0 <= y < top needs bounds checking. */
 
     for (y = 0; y < GBH; y++) {
-        int bit = jbig2_arith_decode(as, &GB_stats[0x9B25]);
+        int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x9B25]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
         LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
@@ -1062,9 +1062,9 @@
                         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
                         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
                     }
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                     if (bit < 0)
-                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
+                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
                 }
                 pd = pd<<1;
                 ppd = ppd<<1;
@@ -1107,9 +1107,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        int bit = jbig2_arith_decode(as, &GB_stats[0x0795]);
+        int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x0795]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON1");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON1");
         LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
@@ -1137,9 +1137,9 @@
                     CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
                     CONTEXT |= (pd>>9) & 0x01F0; /* next 5 pixels */
                     CONTEXT |= (ppd>>4) & 0x1E00; /* next 4 pixels */
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                     if (bit < 0)
-                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON2");
+                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON2");
                 }
                 pd = pd<<1;
                 ppd = ppd<<1;
@@ -1182,9 +1182,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        int bit = jbig2_arith_decode(as, &GB_stats[0xE5]);
+        int bit = jbig2_arith_decode(ctx, as, &GB_stats[0xE5]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON1");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON1");
         LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
@@ -1212,9 +1212,9 @@
                     CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
                     CONTEXT |= (pd>>11) & 0x078; /* next 4 pixels */
                     CONTEXT |= (ppd>>7) & 0x380; /* next 3 pixels */
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                     if (bit < 0)
-                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON2");
+                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON2");
                 }
                 pd = pd<<1;
                 ppd = ppd<<1;
@@ -1257,9 +1257,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        int bit = jbig2_arith_decode(as, &GB_stats[0x0195]);
+        int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x0195]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON1");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON1");
         LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
@@ -1279,9 +1279,9 @@
                     CONTEXT  = out_byte & 0x0F; /* First 4 pixels */
                     CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
                     CONTEXT |= (pd>>9) & 0x3E0; /* next 5 pixels */
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
                     if (bit < 0)
-                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON2");
+                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON2");
                 }
                 pd = pd<<1;
                 out_byte = (out_byte<<1) | bit;
--- a/jbig2_huffman.c
+++ b/jbig2_huffman.c
@@ -58,7 +58,7 @@
 };
 
 #define huff_get_next_word(hs, offset, word) \
-    (hs)->ws->get_next_word((hs)->ws, (offset), (word))
+    (hs)->ws->get_next_word((hs)->ctx, (hs)->ws, (offset), (word))
 
 /** Allocate and initialize a new huffman coding state
  *  the returned pointer can simply be freed; this does
@@ -718,7 +718,7 @@
 static const byte test_tabindex[] = { 4, 2, 2, 1 };
 
 static int
-test_get_word1(Jbig2WordStream *self, size_t offset, uint32_t *word)
+test_get_word1(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word)
 {
     uint32_t val = 0;
     int ret = 0;
@@ -2029,7 +2029,7 @@
 } test_stream_t;
 
 static int
-test_get_word2(Jbig2WordStream *self, size_t offset, uint32_t *word)
+test_get_word2(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word)
 {
     test_stream_t *st = (test_stream_t *) self;
     uint32_t val = 0;
--- a/jbig2_priv.h
+++ b/jbig2_priv.h
@@ -139,7 +139,7 @@
 typedef struct _Jbig2WordStream Jbig2WordStream;
 
 struct _Jbig2WordStream {
-    int (*get_next_word)(Jbig2WordStream *self, size_t offset, uint32_t *word);
+    int (*get_next_word)(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word);
 };
 
 Jbig2WordStream *jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size);
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -80,9 +80,9 @@
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
-            bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+            bit = jbig2_arith_decode(ctx, as, &GR_stats[CONTEXT]);
             if (bit < 0)
-                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template0");
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling refinement template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
     }
@@ -134,9 +134,9 @@
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
-            bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+            bit = jbig2_arith_decode(ctx, as, &GR_stats[CONTEXT]);
             if (bit < 0)
-                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template0");
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling refinement template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
     }
@@ -211,9 +211,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 int bit;
 
-                bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+                bit = jbig2_arith_decode(ctx, as, &GR_stats[CONTEXT]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template1");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling refinement template1");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x0d6) << 1) | bit |
                           ((line_m1 >> (9 - x_minor)) & 0x002) |
@@ -316,15 +316,15 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GRH; y++) {
-        int bit = jbig2_arith_decode(as, &GR_stats[start_context]);
+        int bit = jbig2_arith_decode(ctx, as, &GR_stats[start_context]);
         if (bit < 0)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
         LTP ^= bit;
         if (!LTP) {
             for (x = 0; x < GRW; x++) {
-                bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+                bit = jbig2_arith_decode(ctx, as, &GR_stats[mkctx(params, image, x, y)]);
                 if (bit < 0)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
         } else {
@@ -331,9 +331,9 @@
             for (x = 0; x < GRW; x++) {
                 iv = implicit_value(params, image, x, y);
                 if (iv < 0) {
-                    int bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+                    int bit = jbig2_arith_decode(ctx, as, &GR_stats[mkctx(params, image, x, y)]);
                     if (bit < 0)
-                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
+                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
                     jbig2_image_set_pixel(image, x, y, bit);
                 } else
                     jbig2_image_set_pixel(image, x, y, iv);