shithub: jbig2

Download patch

ref: 471dabc8b157f9a841e4f0090e3c2ff016915fd9
parent: 398186762d6f73d1632d8c6d846f2066c3087751
author: Sebastian Rasmussen <sebras@gmail.com>
date: Thu Apr 5 20:41:01 EDT 2018

jbig2dec: Improve error handling.

Some functions detected errors but would not return these
to the caller. These functions may now indicate errors:

  jbig2_arith_decode(), jbig2_image_resize()

Errors detected by following functions were not always
handled, but they are now handled properly:

  jbig2_arith_decode(), jbig2_arith_iaid_decode()
  jbig2_arith_int_ctx_new(), jbig2_build_huffman_table()
  jbig2_complete_page(), jbig2_image_compose()
  jbig2_decode_refinement_region(), jbig2_ctx_new()
  jbig2_image_resize(), jbig2_image_write_pbm()
  jbig2_image_write_pbm_file(), jbig2_image_write_png()
  jbig2_image_write_png_file(), jbig2_metadata_add()
  jbig2_page_add_result(), jbig2_renew()
  jbig2_strndup()

Some functions detected errors but did not fail early enough:

  jbig2_decode_pattern_dict(), jbig2_decode_halftone_region()

jbig2_decode_mmr_line() detected errors but did not produce
suitable error messages. This has been rectified.

Finally, if a subfunction indicates an error by returning an
error code, the calling function will report a warning and
return, indicating failure.

--- a/jbig2.c
+++ b/jbig2.c
@@ -294,7 +294,17 @@
             ctx->buf_rd_ix += header_size;
 
             if (ctx->n_segments == ctx->n_segments_max)
-                ctx->segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
+            {
+                Jbig2Segment **segments;
+                segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
+                if (segments == NULL)
+                {
+                    ctx->state = JBIG2_FILE_EOF;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "could not reallocate space for more segments");
+                }
+                ctx->segments = segments;
+            }
+
 
             ctx->segments[ctx->n_segments++] = segment;
             if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) {
--- a/jbig2_arith.c
+++ b/jbig2_arith.c
@@ -263,7 +263,7 @@
 }
 
 bool
-jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx)
+jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx, int *code)
 {
     Jbig2ArithCx cx = *pcx;
     const Jbig2ArithQe *pqe;
@@ -271,7 +271,8 @@
     bool D;
 
     if (index >= MAX_QE_ARRAY_SIZE) {
-        return -1;
+        *code = -1;
+        return 0;
     } else {
         pqe = &jbig2_arith_Qe[index];
     }
@@ -354,6 +355,7 @@
     Jbig2ArithState *as;
     int i;
     Jbig2ArithCx cx = 0;
+    int code;
 
     ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL);
 
@@ -369,7 +371,7 @@
 #else
         (void)
 #endif
-            jbig2_arith_decode(as, &cx);
+            jbig2_arith_decode(as, &cx, &code);
 
 #ifdef JBIG2_DEBUG_ARITH
         fprintf(stderr, "%3d: D = %d, ", i, D);
--- a/jbig2_arith.h
+++ b/jbig2_arith.h
@@ -28,7 +28,7 @@
 Jbig2ArithState *jbig2_arith_new(Jbig2Ctx *ctx, Jbig2WordStream *ws);
 
 /* decode a bit */
-bool            jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx);
+bool            jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx, int *code);
 
 /* 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
@@ -66,17 +66,20 @@
 /* A.3 */
 /* Return value: -1 on error, 0 on normal value */
 int
-jbig2_arith_iaid_decode(Jbig2ArithIaidCtx *ctx, Jbig2ArithState *as, int32_t *p_result)
+jbig2_arith_iaid_decode(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *actx, Jbig2ArithState *as, int32_t *p_result)
 {
-    Jbig2ArithCx *IAIDx = ctx->IAIDx;
-    int SBSYMCODELEN = ctx->SBSYMCODELEN;
+    Jbig2ArithCx *IAIDx = actx->IAIDx;
+    int SBSYMCODELEN = actx->SBSYMCODELEN;
     int PREV = 1;
     int D;
     int i;
+    int code = 0;
 
     /* A.3 (2) */
     for (i = 0; i < SBSYMCODELEN; i++) {
-        D = jbig2_arith_decode(as, &IAIDx[PREV]);
+        D = jbig2_arith_decode(as, &IAIDx[PREV], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAIDx code");
 #ifdef VERBOSE
         fprintf(stderr, "IAID%x: D = %d\n", PREV, D);
 #endif
--- a/jbig2_arith_iaid.h
+++ b/jbig2_arith_iaid.h
@@ -21,6 +21,6 @@
 
 Jbig2ArithIaidCtx *jbig2_arith_iaid_ctx_new(Jbig2Ctx *ctx, int SBSYMCODELEN);
 
-int jbig2_arith_iaid_decode(Jbig2ArithIaidCtx *ctx, Jbig2ArithState *as, int32_t *p_result);
+int jbig2_arith_iaid_decode(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *actx, Jbig2ArithState *as, int32_t *p_result);
 
 void jbig2_arith_iaid_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *iax);
--- a/jbig2_arith_int.c
+++ b/jbig2_arith_int.c
@@ -53,34 +53,47 @@
 /* A.2 */
 /* Return value: -1 on error, 0 on normal value, 1 on OOB return. */
 int
-jbig2_arith_int_decode(Jbig2ArithIntCtx *ctx, Jbig2ArithState *as, int32_t *p_result)
+jbig2_arith_int_decode(Jbig2Ctx *ctx, Jbig2ArithIntCtx *actx, Jbig2ArithState *as, int32_t *p_result)
 {
-    Jbig2ArithCx *IAx = ctx->IAx;
+    Jbig2ArithCx *IAx = actx->IAx;
     int PREV = 1;
     int S, V;
     int bit;
     int n_tail, offset;
     int i;
+    int code = 0;
 
-    S = jbig2_arith_decode(as, &IAx[PREV]);
+    S = jbig2_arith_decode(as, &IAx[PREV], &code);
+    if (code)
+        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx S");
     PREV = (PREV << 1) | S;
 
-    bit = jbig2_arith_decode(as, &IAx[PREV]);
+    bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+    if (code)
+        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 0");
     PREV = (PREV << 1) | bit;
     if (bit) {
-        bit = jbig2_arith_decode(as, &IAx[PREV]);
+        bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 1");
         PREV = (PREV << 1) | bit;
 
         if (bit) {
-            bit = jbig2_arith_decode(as, &IAx[PREV]);
+            bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+            if (code)
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 2");
             PREV = (PREV << 1) | bit;
 
             if (bit) {
-                bit = jbig2_arith_decode(as, &IAx[PREV]);
+                bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 3");
                 PREV = (PREV << 1) | bit;
 
                 if (bit) {
-                    bit = jbig2_arith_decode(as, &IAx[PREV]);
+                    bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+                    if (code)
+                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 4");
                     PREV = (PREV << 1) | bit;
 
                     if (bit) {
@@ -109,7 +122,9 @@
 
     V = 0;
     for (i = 0; i < n_tail; i++) {
-        bit = jbig2_arith_decode(as, &IAx[PREV]);
+        bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx code 7");
         PREV = ((PREV << 1) & 511) | (PREV & 256) | bit;
         V = (V << 1) | bit;
     }
--- a/jbig2_arith_int.h
+++ b/jbig2_arith_int.h
@@ -21,6 +21,6 @@
 
 Jbig2ArithIntCtx *jbig2_arith_int_ctx_new(Jbig2Ctx *ctx);
 
-int jbig2_arith_int_decode(Jbig2ArithIntCtx *ctx, Jbig2ArithState *as, int32_t *p_result);
+int jbig2_arith_int_decode(Jbig2Ctx *ctx, Jbig2ArithIntCtx *actx, Jbig2ArithState *as, int32_t *p_result);
 
 void jbig2_arith_int_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIntCtx *iax);
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -76,6 +76,7 @@
         uint32_t line_m1;
         uint32_t line_m2;
         int padded_width = (GBW + 7) & -8;
+        int code = 0;
 
         line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
         line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0;
@@ -97,7 +98,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 bool bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit | ((line_m1 >> (7 - x_minor)) & 0x10) | ((line_m2 >> (7 - x_minor)) & 0x800);
             }
@@ -125,6 +128,7 @@
     uint32_t CONTEXT;
     int x, y;
     bool bit;
+    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
         pixel_outside_field(params->gbat[2], params->gbat[3]) ||
@@ -154,7 +158,9 @@
             CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
             CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
             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(as, &GB_stats[CONTEXT], &code);
+            if (code)
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
     }
@@ -171,6 +177,7 @@
     const int rowstride = image->stride;
     int x, y;
     byte *gbreg_line = (byte *) image->data;
+    int code = 0;
 
     /* todo: currently we only handle the nominal gbat location */
     /* when resolved make sure to call jbig2_check_adaptive_pixel_in_field() */
@@ -208,7 +215,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 bool bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template1");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0xefb) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x8) | ((line_m2 >> (8 - x_minor)) & 0x200);
             }
@@ -233,6 +242,7 @@
     const int rowstride = image->stride;
     int x, y;
     byte *gbreg_line = (byte *) image->data;
+    int code = 0;
 
     /* todo: currently we only handle the nominal gbat location */
     /* when resolved make sure to call jbig2_check_adaptive_pixel_in_field() */
@@ -270,7 +280,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 bool bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
             }
@@ -295,6 +307,7 @@
     const int rowstride = image->stride;
     int x, y;
     byte *gbreg_line = (byte *) image->data;
+    int code = 0;
 
     /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
 
@@ -331,7 +344,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 bool bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2a");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
                           ((line_m1 >> (10 - x_minor)) & 0x8) | ((line_m1 >> (9 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
@@ -389,7 +404,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 bool bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x010);
             }
@@ -415,6 +432,7 @@
     uint32_t CONTEXT;
     int x, y;
     bool bit;
+    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -435,7 +453,9 @@
             CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
             CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
             CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
-            bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+            bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+            if (code)
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3");
             jbig2_image_set_pixel(image, x, y, bit);
         }
     }
@@ -467,6 +487,7 @@
     int x, y;
     bool bit;
     int LTP = 0;
+    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
         pixel_outside_field(params->gbat[2], params->gbat[3]) ||
@@ -476,7 +497,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25]);
+        LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0 TPGDON1");
         if (!LTP) {
             for (x = 0; x < GBW; x++) {
                 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -495,7 +518,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 13;
                 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
                 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(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0 TPGDON2");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
         } else {
@@ -517,6 +542,7 @@
     int x, y;
     bool bit;
     int LTP = 0;
+    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -523,7 +549,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795]);
+        LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template1 TPGDON1");
         if (!LTP) {
             for (x = 0; x < GBW; x++) {
                 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -539,7 +567,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
                 CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 11;
                 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template1 TPGDON2");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
         } else {
@@ -561,6 +591,7 @@
     int x, y;
     bool bit;
     int LTP = 0;
+    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -567,7 +598,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5]);
+        LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2 TPGDON1");
         if (!LTP) {
             for (x = 0; x < GBW; x++) {
                 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -580,7 +613,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
                 CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 8;
                 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2 TPGDON2");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
         } else {
@@ -602,6 +637,7 @@
     int x, y;
     bool bit;
     int LTP = 0;
+    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -608,7 +644,9 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195]);
+        LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3 TPGDON1");
         if (!LTP) {
             for (x = 0; x < GBW; x++) {
                 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -621,7 +659,9 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
                 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
                 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3 TPGDON2");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
         } else {
@@ -791,8 +831,9 @@
     }
 
     if (code >= 0)
-        jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
-    else
+        code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
+
+    if (code < 0)
         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error while decoding immediate_generic_region");
 
 cleanup:
--- a/jbig2_halftone.c
+++ b/jbig2_halftone.c
@@ -44,7 +44,9 @@
     const int N = params->GRAYMAX + 1;
     const int HPW = params->HDPW;
     const int HPH = params->HDPH;
+    int code;
     int i;
+    int j;
 
     /* allocate a new struct */
     new = jbig2_new(ctx, Jbig2PatternDict, 1);
@@ -63,7 +65,6 @@
         for (i = 0; i < N; i++) {
             new->patterns[i] = jbig2_image_new(ctx, HPW, HPH);
             if (new->patterns[i] == NULL) {
-                int j;
 
                 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to allocate pattern element image");
                 for (j = 0; j < i; j++)
@@ -74,7 +75,14 @@
             /* compose with the REPLACE operator; the source
                will be clipped to the destination, selecting the
                proper sub image */
-            jbig2_image_compose(ctx, new->patterns[i], image, -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
+            code = jbig2_image_compose(ctx, new->patterns[i], image, -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to compose image into collective bitmap dictionary");
+                for (j = 0; j < i; j++)
+                    jbig2_free(ctx->allocator, new->patterns[j]);
+                jbig2_free(ctx->allocator, new);
+                return NULL;
+            }
         }
     } else {
         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate collective bitmap dictionary");
@@ -169,6 +177,8 @@
 
     if (code == 0)
         hd = jbig2_hd_new(ctx, params, image);
+    else
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error while decoding immediate_generic_region");
     jbig2_image_release(ctx, image);
 
     return hd;
@@ -452,6 +462,7 @@
     uint32_t mg, ng;
     int32_t x, y;
     uint8_t gray_val;
+    int code;
 
     /* 6.6.5 point 1. Fill bitmap with HDEFPIXEL */
     memset(image->data, params->HDEFPIXEL, image->stride * image->height);
@@ -498,7 +509,11 @@
                 /* use highest available pattern */
                 gray_val = HNUMPATS - 1;
             }
-            jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
+            code = jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose pattern with gray-scale image");
+                return -1;
+            }
         }
     }
 
@@ -592,6 +607,10 @@
     }
 
     code = jbig2_decode_halftone_region(ctx, segment, &params, segment_data + offset, segment->data_length - offset, image, GB_stats);
+    if (code < 0) {
+        jbig2_image_release(ctx, image);
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to decode halftone region");
+    }
 
     /* todo: retain GB_stats? */
     if (!params.HMMR) {
@@ -598,7 +617,13 @@
         jbig2_free(ctx->allocator, GB_stats);
     }
 
-    jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+    code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+    if (code < 0)
+    {
+        jbig2_image_release(ctx, image);
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable add halftone region to page");
+    }
+
     jbig2_image_release(ctx, image);
 
     return code;
--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -132,7 +132,7 @@
         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "jbig2_image_resize called with a different width (NYI)");
     }
 
-    return NULL;
+    return image;
 }
 
 /* composite one jbig2_image onto another
--- a/jbig2_image_pbm.c
+++ b/jbig2_image_pbm.c
@@ -35,7 +35,7 @@
 jbig2_image_write_pbm_file(Jbig2Image *image, char *filename)
 {
     FILE *out;
-    int error;
+    int code;
 
     if ((out = fopen(filename, "wb")) == NULL) {
         fprintf(stderr, "unable to open '%s' for writing", filename);
@@ -42,10 +42,10 @@
         return 1;
     }
 
-    error = jbig2_image_write_pbm(image, out);
+    code = jbig2_image_write_pbm(image, out);
 
     fclose(out);
-    return (error);
+    return (code);
 }
 
 /* write out an image struct as a pbm stream to an open file pointer */
--- a/jbig2_image_png.c
+++ b/jbig2_image_png.c
@@ -138,7 +138,7 @@
 jbig2_image_write_png_file(Jbig2Image *image, char *filename)
 {
     FILE *out;
-    int error;
+    int code;
 
     if ((out = fopen(filename, "wb")) == NULL) {
         fprintf(stderr, "unable to open '%s' for writing\n", filename);
@@ -145,8 +145,8 @@
         return 1;
     }
 
-    error = jbig2_image_write_png(image, out);
+    code = jbig2_image_write_png(image, out);
 
     fclose(out);
-    return (error);
+    return (code);
 }
--- a/jbig2_metadata.c
+++ b/jbig2_metadata.c
@@ -107,6 +107,11 @@
     /* copy the passed key,value pair */
     md->keys[md->entries] = jbig2_strndup(ctx, key, key_length);
     md->values[md->entries] = jbig2_strndup(ctx, value, value_length);
+    if (md->keys[md->entries] == NULL || md->values[md->entries] == NULL)
+    {
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to accomodate more metadata");
+        return -1;
+    }
     md->entries++;
 
     return 0;
@@ -120,6 +125,7 @@
     char *end = (char *)(segment_data + segment->data_length);
     Jbig2Metadata *comment;
     char *key, *value;
+    int code;
 
     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "ASCII comment data");
 
@@ -139,7 +145,11 @@
         if (!s)
             goto too_short;
         s++;
-        jbig2_metadata_add(ctx, comment, key, value - key, value, s - value);
+        code = jbig2_metadata_add(ctx, comment, key, value - key, value, s - value);
+        if (code < 0) {
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add ascii comment data");
+            return -1;
+        }
         jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "'%s'\t'%s'", key, value);
     }
 
--- a/jbig2_mmr.c
+++ b/jbig2_mmr.c
@@ -831,7 +831,7 @@
 }
 
 static int
-jbig2_decode_mmr_line(Jbig2MmrCtx *mmr, const byte *ref, byte *dst)
+jbig2_decode_mmr_line(Jbig2Ctx *ctx, Jbig2MmrCtx *mmr, const byte *ref, byte *dst)
 {
     uint32_t a0 = MINUS1;
     uint32_t a1, a2, b1, b2;
@@ -863,7 +863,7 @@
                 if (a2 > mmr->width)
                     a2 = mmr->width;
                 if (a1 == MINUS1 || a2 < a1)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative black run");
                 jbig2_set_bits(dst, a1, a2);
                 a0 = a2;
                 /* printf ("H %d %d\n", white_run, black_run); */
@@ -877,7 +877,7 @@
                 if (a2 > mmr->width)
                     a2 = mmr->width;
                 if (a0 == MINUS1 || a1 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, a1);
                 a0 = a2;
                 /* printf ("H %d %d\n", black_run, white_run); */
@@ -891,7 +891,7 @@
             b2 = jbig2_find_changing_element(ref, b1, mmr->width);
             if (c) {
                 if (a0 == MINUS1 || b2 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b2);
             }
             a0 = b2;
@@ -903,7 +903,7 @@
             b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
             if (c) {
                 if (a0 == MINUS1 || b1 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1);
             }
             a0 = b1;
@@ -918,7 +918,7 @@
                 break;
             if (c) {
                 if (a0 == MINUS1 || b1 + 1 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1 + 1);
             }
             a0 = b1 + 1;
@@ -933,7 +933,7 @@
                 break;
             if (c) {
                 if (a0 == MINUS1 || b1 + 2 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1 + 2);
             }
             a0 = b1 + 2;
@@ -948,7 +948,7 @@
                 break;
             if (c) {
                 if (a0 == MINUS1 || b1 + 3 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1 + 3);
             }
             a0 = b1 + 3;
@@ -963,7 +963,7 @@
                 break;
             if (c) {
                 if (a0 == MINUS1 || b1 - 1 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1 - 1);
             }
             a0 = b1 - 1;
@@ -978,7 +978,7 @@
                 break;
             if (c) {
                 if (a0 == MINUS1 || b1 - 2 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1 - 2);
             }
             a0 = b1 - 2;
@@ -993,7 +993,7 @@
                 break;
             if (c) {
                 if (a0 == MINUS1 || b1 - 3 < a0)
-                    return -1;
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
                 jbig2_set_bits(dst, a0, b1 - 3);
             }
             a0 = b1 - 3;
@@ -1021,9 +1021,12 @@
 
     for (y = 0; y < image->height; y++) {
         memset(dst, 0, rowstride);
-        code = jbig2_decode_mmr_line(&mmr, ref, dst);
+        code = jbig2_decode_mmr_line(ctx, &mmr, ref, dst);
         if (code < 0)
+        {
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode mmr line");
             return code;
+        }
         ref = dst;
         dst += rowstride;
     }
@@ -1060,9 +1063,12 @@
 
     for (y = 0; y < image->height; y++) {
         memset(dst, 0, rowstride);
-        code = jbig2_decode_mmr_line(&mmr, ref, dst);
+        code = jbig2_decode_mmr_line(ctx, &mmr, ref, dst);
         if (code < 0)
+        {
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode halftone mmr line");
             return code;
+        }
         ref = dst;
         dst += rowstride;
     }
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -59,7 +59,7 @@
 int
 jbig2_page_info(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
 {
-    Jbig2Page *page;
+    Jbig2Page *page, *pages;
 
     /* a new page info segment implies the previous page is finished */
     page = &(ctx->pages[ctx->current_page]);
@@ -77,7 +77,11 @@
             index++;
             if (index >= ctx->max_page_index) {
                 /* grow the list */
-                ctx->pages = jbig2_renew(ctx, ctx->pages, Jbig2Page, (ctx->max_page_index <<= 2));
+                pages = jbig2_renew(ctx, ctx->pages, Jbig2Page, (ctx->max_page_index <<= 2));
+                if (pages == NULL) {
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to reallocate space for more pages");
+                }
+                ctx->pages = pages;
                 for (j = index; j < ctx->max_page_index; j++) {
                     ctx->pages[j].state = JBIG2_PAGE_FREE;
                     ctx->pages[j].number = 0;
@@ -200,7 +204,7 @@
     }
 
     /* ensure image exists before marking page as complete */
-    if (ctx->pages[ctx->current_page].image != NULL) {
+    if (!code && ctx->pages[ctx->current_page].image != NULL) {
         ctx->pages[ctx->current_page].state = JBIG2_PAGE_COMPLETE;
     }
 
@@ -214,6 +218,7 @@
 jbig2_end_of_page(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
 {
     uint32_t page_number = ctx->pages[ctx->current_page].number;
+    int code;
 
     if (segment->page_association != page_number) {
         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
@@ -222,10 +227,17 @@
 
     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of page %d", page_number);
 
-    jbig2_complete_page(ctx);
+    code = jbig2_complete_page(ctx);
+    if (code < 0) {
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to complete page");
+        return -1;
+    }
 
 #ifdef OUTPUT_PBM
-    jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
+    code = jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
+    if (code < 0) {
+        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "failed to write page image");
+    }
 #endif
 
     return 0;
@@ -240,6 +252,8 @@
 int
 jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *image, int x, int y, Jbig2ComposeOp op)
 {
+    int code;
+
     /* ensure image exists first */
     if (page->image == NULL) {
         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "page info possibly missing, no image defined");
@@ -251,12 +265,21 @@
         uint32_t new_height = y + image->height + page->end_row;
 
         if (page->image->height < new_height) {
+            Jbig2Image *resized_image = NULL;
             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "growing page buffer to %d rows " "to accomodate new stripe", new_height);
-            jbig2_image_resize(ctx, page->image, page->image->width, new_height);
+            resized_image = jbig2_image_resize(ctx, page->image, page->image->width, new_height);
+            if (resized_image == NULL) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "unable to resize image to accomodate new stripe");
+            }
+            page->image = resized_image;
         }
     }
 
-    jbig2_image_compose(ctx, page->image, image, x, y + page->end_row, op);
+    code = jbig2_image_compose(ctx, page->image, image, x, y + page->end_row, op);
+    if (code < 0) {
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to compose image with page");
+        return -1;
+    }
 
     return 0;
 }
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -60,6 +60,7 @@
     uint32_t CONTEXT;
     int x, y;
     bool bit;
+    int code = 0;
 
     for (y = 0; y < GRH; y++) {
         for (x = 0; x < GRW; x++) {
@@ -77,7 +78,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(as, &GR_stats[CONTEXT], &code);
+            if (code)
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
     }
@@ -85,11 +88,16 @@
     {
         static count = 0;
         char name[32];
+        int code;
 
         snprintf(name, 32, "refin-%d.pbm", count);
-        jbig2_image_write_pbm_file(ref, name);
+        code = jbig2_image_write_pbm_file(ref, name);
+        if (code < 0)
+            return jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed write refinement input");
         snprintf(name, 32, "refout-%d.pbm", count);
-        jbig2_image_write_pbm_file(image, name);
+        code = jbig2_image_write_pbm_file(image, name);
+        if (code < 0)
+            return jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed write refinement output");
         count++;
     }
 #endif
@@ -110,6 +118,7 @@
     uint32_t CONTEXT;
     int x, y;
     bool bit;
+    int code = 0;
 
     for (y = 0; y < GRH; y++) {
         for (x = 0; x < GRW; x++) {
@@ -124,7 +133,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(as, &GR_stats[CONTEXT], &code);
+            if (code)
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
     }
@@ -135,9 +146,13 @@
         char name[32];
 
         snprintf(name, 32, "refin-%d.pbm", count);
-        jbig2_image_write_pbm_file(ref, name);
+        code = jbig2_image_write_pbm_file(ref, name);
+        if (code < 0)
+            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed to write refinement input");
         snprintf(name, 32, "refout-%d.pbm", count);
-        jbig2_image_write_pbm_file(image, name);
+        code = jbig2_image_write_pbm_file(image, name);
+        if (code < 0)
+            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed to write refinement output");
         count++;
     }
 #endif
@@ -159,6 +174,7 @@
     byte *grreg_line = (byte *) image->data;
     byte *grref_line = (byte *) params->reference->data;
     int x, y;
+    int code = 0;
 
     for (y = 0; y < GRH; y++) {
         const int padded_width = (GRW + 7) & -8;
@@ -195,7 +211,9 @@
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
                 bool bit;
 
-                bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+                bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "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) |
@@ -281,7 +299,7 @@
 }
 
 static int
-jbig2_decode_refinement_TPGRON(const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
+jbig2_decode_refinement_TPGRON(Jbig2Ctx *ctx, const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
 {
     const int GRW = image->width;
     const int GRH = image->height;
@@ -288,12 +306,17 @@
     int x, y, iv, bit, LTP = 0;
     uint32_t start_context = (params->GRTEMPLATE ? 0x40 : 0x100);
     ContextBuilder mkctx = (params->GRTEMPLATE ? mkctx1 : mkctx0);
+    int code = 0;
 
     for (y = 0; y < GRH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GR_stats[start_context]);
+        LTP ^= jbig2_arith_decode(as, &GR_stats[start_context], &code);
+        if (code)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
         if (!LTP) {
             for (x = 0; x < GRW; x++) {
-                bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+                bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
+                if (code)
+                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
         } else {
@@ -300,7 +323,9 @@
             for (x = 0; x < GRW; x++) {
                 iv = implicit_value(params, image, x, y);
                 if (iv < 0) {
-                    bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+                    bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
+                    if (code)
+                        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -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);
@@ -340,7 +365,7 @@
     }
 
     if (params->TPGRON)
-        return jbig2_decode_refinement_TPGRON(params, as, image, GR_stats);
+        return jbig2_decode_refinement_TPGRON(ctx, params, as, image, GR_stats);
 
     if (params->GRTEMPLATE)
         return jbig2_decode_refinement_template1_unopt(ctx, segment, params, as, image, GR_stats);
@@ -485,6 +510,10 @@
         }
 
         code = jbig2_decode_refinement_region(ctx, segment, &params, as, image, GR_stats);
+        if (code < 0) {
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to decode refinement region");
+            goto cleanup;
+        }
 
         if ((segment->flags & 63) == 40) {
             /* intermediate region. save the result for later */
@@ -493,7 +522,11 @@
             /* immediate region. composite onto the page */
             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
                         "composing %dx%d decoded refinement region onto page at (%d, %d)", rsi.width, rsi.height, rsi.x, rsi.y);
-            jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
+            code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to add refinement region to page");
+                goto cleanup;
+            }
         }
 
 cleanup:
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -76,7 +76,7 @@
     referred_to_segment_size = result->number <= 256 ? 1 : result->number <= 65536 ? 2 : 4;     /* 7.2.5 */
     pa_size = result->flags & 0x40 ? 4 : 1;     /* 7.2.6 */
     if (offset + referred_to_segment_count * referred_to_segment_size + pa_size + 4 > buf_size) {
-        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "jbig2_parse_segment_header() called with insufficient data", -1);
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, result->number, "jbig2_parse_segment_header() called with insufficient data", -1);
         jbig2_free(ctx->allocator, result);
         return NULL;
     }
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -70,6 +70,7 @@
     Jbig2SymbolDict *dict = (Jbig2SymbolDict *) segment->result;
     int index;
     char filename[24];
+    int code;
 
     if (dict == NULL)
         return;
@@ -78,10 +79,12 @@
         snprintf(filename, sizeof(filename), "symbol_%02d-%04d.png", segment->number, index);
         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "dumping symbol %d/%d as '%s'", index, dict->n_symbols, filename);
 #ifdef HAVE_LIBPNG
-        jbig2_image_write_png_file(dict->glyphs[index], filename);
+        code = jbig2_image_write_png_file(dict->glyphs[index], filename);
 #else
-        jbig2_image_write_pbm_file(dict->glyphs[index], filename);
+        code = jbig2_image_write_pbm_file(dict->glyphs[index], filename);
 #endif
+        if (code < 0)
+            jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "failed to dump symbol %d/%d as '%s'", index, dict->n_symbols, filename);
     }
 }
 #endif /* DUMP_SYMDICT */
@@ -318,7 +321,7 @@
         if (params->SDHUFF) {
             HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code);
         } else {
-            code = jbig2_arith_int_decode(IADH, as, &HCDH);
+            code = jbig2_arith_int_decode(ctx, IADH, as, &HCDH);
         }
 
         if (code != 0) {
@@ -350,7 +353,7 @@
             if (params->SDHUFF) {
                 DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
             } else {
-                code = jbig2_arith_int_decode(IADW, as, &DW);
+                code = jbig2_arith_int_decode(ctx, IADW, as, &DW);
             }
             if (code < 0)
                 goto cleanup4;
@@ -415,7 +418,7 @@
                     if (params->SDHUFF) {
                         REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
                     } else {
-                        code = jbig2_arith_int_decode(IAAI, as, (int32_t *) & REFAGGNINST);
+                        code = jbig2_arith_int_decode(ctx, IAAI, as, (int32_t *) & REFAGGNINST);
                     }
                     if (code || (int32_t) REFAGGNINST <= 0) {
                         code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid number of symbols or OOB in aggregate glyph");
@@ -465,6 +468,14 @@
                                 tparams->IARDH = jbig2_arith_int_ctx_new(ctx);
                                 tparams->IARDX = jbig2_arith_int_ctx_new(ctx);
                                 tparams->IARDY = jbig2_arith_int_ctx_new(ctx);
+                                if ((tparams->IAID == NULL) || (tparams->IAFS == NULL) ||
+                                    (tparams->IADS == NULL) || (tparams->IAIT == NULL) ||
+                                    (tparams->IAID == NULL) || (tparams->IARDW == NULL) ||
+                                    (tparams->IARDH == NULL) || (tparams->IARDX == NULL) ||
+                                    (tparams->IARDY == NULL)) {
+                                    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "out of memory creating text region arith decoder entries");
+                                    goto cleanup4;
+                                }
                             } else {
                                 tparams->SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F);    /* Table B.6 */
                                 tparams->SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H);    /* Table B.8 */
@@ -473,6 +484,13 @@
                                 tparams->SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
                                 tparams->SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
                                 tparams->SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
+                                if ((tparams->SBHUFFFS == NULL) || (tparams->SBHUFFDS == NULL) ||
+                                    (tparams->SBHUFFDT == NULL) || (tparams->SBHUFFRDW == NULL) ||
+                                    (tparams->SBHUFFRDH == NULL) || (tparams->SBHUFFRDX == NULL) ||
+                                    (tparams->SBHUFFRDY == NULL)) {
+                                    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "out of memory creating text region huffman decoder entries");
+                                    goto cleanup4;
+                                }
                             }
                             tparams->SBHUFF = params->SDHUFF;
                             tparams->SBREFINE = 1;
@@ -522,9 +540,9 @@
                             BMSIZE = jbig2_huffman_get(hs, SBHUFFRSIZE, &code3);
                             jbig2_huffman_skip(hs);
                         } else {
-                            code1 = jbig2_arith_iaid_decode(IAID, as, (int32_t *) & ID);
-                            code2 = jbig2_arith_int_decode(IARDX, as, &RDX);
-                            code3 = jbig2_arith_int_decode(IARDY, as, &RDY);
+                            code1 = jbig2_arith_iaid_decode(ctx, IAID, as, (int32_t *) & ID);
+                            code2 = jbig2_arith_int_decode(ctx, IARDX, as, &RDX);
+                            code3 = jbig2_arith_int_decode(ctx, IARDY, as, &RDY);
                         }
 
                         if ((code1 < 0) || (code2 < 0) || (code3 < 0) || (code4 < 0)) {
@@ -578,11 +596,15 @@
                 {
                     char name[64];
                     FILE *out;
+                    int code;
 
                     snprintf(name, 64, "sd.%04d.%04d.pbm", segment->number, NSYMSDECODED);
                     out = fopen(name, "wb");
-                    jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
-                    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "writing out glyph as '%s' ...", name);
+                    code = jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
+                    if (code < 0)
+                        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "failed to write glyph");
+                    else
+                        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "writing out glyph as '%s' ...", name);
                     fclose(out);
                 }
 #endif
@@ -682,7 +704,13 @@
                     jbig2_image_release(ctx, image);
                     goto cleanup4;
                 }
-                jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
+                code = jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
+                if (code) {
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose image into glyph");
+                    jbig2_image_release(ctx, glyph);
+                    jbig2_image_release(ctx, image);
+                    goto cleanup4;
+                }
                 x += SDNEWSYMWIDTHS[j];
                 SDNEWSYMS->glyphs[j] = glyph;
             }
@@ -709,7 +737,7 @@
             if (params->SDHUFF)
                 exrunlength = jbig2_huffman_get(hs, SBHUFFRSIZE, &code);
             else
-                code = jbig2_arith_int_decode(IAEX, as, (int32_t *)&exrunlength);
+                code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *)&exrunlength);
             /* prevent infinite loop */
             zerolength = exrunlength > 0 ? 0 : zerolength + 1;
             if (code || (exrunlength > limit - i) || (zerolength > 4) || (exflag && (exrunlength + j > params->SDNUMEXSYMS))) {
--- a/jbig2_text.c
+++ b/jbig2_text.c
@@ -207,10 +207,12 @@
     if (params->SBHUFF) {
         STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
     } else {
-        code = jbig2_arith_int_decode(params->IADT, as, &STRIPT);
+        code = jbig2_arith_int_decode(ctx, params->IADT, as, &STRIPT);
     }
-    if (code < 0)
+    if (code < 0) {
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain strip T");
         goto cleanup2;
+    }
 
     /* 6.4.5 (2) */
     STRIPT *= -(params->SBSTRIPS);
@@ -223,10 +225,12 @@
         if (params->SBHUFF) {
             DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
         } else {
-            code = jbig2_arith_int_decode(params->IADT, as, &DT);
+            code = jbig2_arith_int_decode(ctx, params->IADT, as, &DT);
         }
-        if (code < 0)
+        if (code < 0) {
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain delta T");
             goto cleanup2;
+        }
         DT *= params->SBSTRIPS;
         STRIPT += DT;
 
@@ -239,10 +243,12 @@
                 if (params->SBHUFF) {
                     DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
                 } else {
-                    code = jbig2_arith_int_decode(params->IAFS, as, &DFS);
+                    code = jbig2_arith_int_decode(ctx, params->IAFS, as, &DFS);
                 }
-                if (code < 0)
+                if (code < 0) {
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain strip symbol S-difference");
                     goto cleanup2;
+                }
                 FIRSTS += DFS;
                 CURS = FIRSTS;
                 first_symbol = FALSE;
@@ -255,7 +261,7 @@
                 if (params->SBHUFF) {
                     IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);
                 } else {
-                    code = jbig2_arith_int_decode(params->IADS, as, &IDS);
+                    code = jbig2_arith_int_decode(ctx, params->IADS, as, &IDS);
                 }
                 if (code) {
                     /* decoded an OOB, reached end of strip */
@@ -270,10 +276,12 @@
             } else if (params->SBHUFF) {
                 CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS, &code);
             } else {
-                code = jbig2_arith_int_decode(params->IAIT, as, &CURT);
+                code = jbig2_arith_int_decode(ctx, params->IAIT, as, &CURT);
             }
-            if (code < 0)
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance T coordinate");
                 goto cleanup2;
+            }
             T = STRIPT + CURT;
 
             /* (3b.iv) / 6.4.10 - decode the symbol id */
@@ -280,10 +288,12 @@
             if (params->SBHUFF) {
                 ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
             } else {
-                code = jbig2_arith_iaid_decode(params->IAID, as, (int *)&ID);
+                code = jbig2_arith_iaid_decode(ctx, params->IAID, as, (int *)&ID);
             }
-            if (code < 0)
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");
                 goto cleanup2;
+            }
             if (ID >= SBNUMSYMS) {
                 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol id out of range! (%d/%d)", ID, SBNUMSYMS);
                 goto cleanup2;
@@ -307,10 +317,12 @@
                 if (params->SBHUFF) {
                     RI = jbig2_huffman_get_bits(hs, 1, &code);
                 } else {
-                    code = jbig2_arith_int_decode(params->IARI, as, &RI);
+                    code = jbig2_arith_int_decode(ctx, params->IARI, as, &RI);
                 }
-                if (code < 0)
+                if (code < 0) {
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol bitmap refinement indicator");
                     goto cleanup2;
+                }
             } else {
                 RI = 0;
             }
@@ -328,10 +340,10 @@
 
                 /* 6.4.11 (1, 2, 3, 4) */
                 if (!params->SBHUFF) {
-                    code1 = jbig2_arith_int_decode(params->IARDW, as, &RDW);
-                    code2 = jbig2_arith_int_decode(params->IARDH, as, &RDH);
-                    code3 = jbig2_arith_int_decode(params->IARDX, as, &RDX);
-                    code4 = jbig2_arith_int_decode(params->IARDY, as, &RDY);
+                    code1 = jbig2_arith_int_decode(ctx, params->IARDW, as, &RDW);
+                    code2 = jbig2_arith_int_decode(ctx, params->IARDH, as, &RDH);
+                    code3 = jbig2_arith_int_decode(ctx, params->IARDX, as, &RDX);
+                    code4 = jbig2_arith_int_decode(ctx, params->IARDY, as, &RDY);
                 } else {
                     RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code1);
                     RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code2);
@@ -373,6 +385,7 @@
                 memcpy(rparams.grat, params->sbrat, 4);
                 code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, refimage, GR_stats);
                 if (code < 0) {
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
                     jbig2_image_release(ctx, refimage);
                     jbig2_image_release(ctx, IBO);
                     goto cleanup2;
@@ -448,6 +461,7 @@
 #endif
             code = jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP);
             if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose symbol instance symbol bitmap into picture");
                 jbig2_image_release(ctx, IB);
                 goto cleanup2;
             }
@@ -877,7 +891,9 @@
         /* otherwise composite onto the page */
         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
                     "composing %dx%d decoded text region onto page at (%d, %d)", region_info.width, region_info.height, region_info.x, region_info.y);
-        jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+        code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+        if (code < 0)
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add text region to page");
     }
 
 cleanup4:
--- a/jbig2dec.c
+++ b/jbig2dec.c
@@ -333,12 +333,10 @@
         switch (params->output_format) {
 #ifdef HAVE_LIBPNG
         case jbig2dec_format_png:
-            jbig2_image_write_png(image, stdout);
-            break;
+            return jbig2_image_write_png(image, stdout);
 #endif
         case jbig2dec_format_pbm:
-            jbig2_image_write_pbm(image, stdout);
-            break;
+            return jbig2_image_write_pbm(image, stdout);
         default:
             fprintf(stderr, "unsupported output format.\n");
             return 1;
@@ -349,12 +347,10 @@
         switch (params->output_format) {
 #ifdef HAVE_LIBPNG
         case jbig2dec_format_png:
-            jbig2_image_write_png_file(image, params->output_file);
-            break;
+            return jbig2_image_write_png_file(image, params->output_file);
 #endif
         case jbig2dec_format_pbm:
-            jbig2_image_write_pbm_file(image, params->output_file);
-            break;
+            return jbig2_image_write_pbm_file(image, params->output_file);
         default:
             fprintf(stderr, "unsupported output format.\n");
             return 1;
@@ -391,6 +387,7 @@
     jbig2dec_params_t params;
     int filearg;
     int result = 1;
+    int code;
 
     /* set defaults */
     params.mode = render;
@@ -449,6 +446,12 @@
         }
 
         ctx = jbig2_ctx_new(NULL, (Jbig2Options)(f_page != NULL ? JBIG2_OPTIONS_EMBEDDED : 0), NULL, error_callback, &params);
+        if (ctx == NULL) {
+            fclose(f);
+            if (f_page)
+                fclose(f_page);
+            goto cleanup;
+        }
 
         /* pull the whole file/global stream into memory */
         for (;;) {
@@ -466,13 +469,15 @@
             Jbig2GlobalCtx *global_ctx = jbig2_make_global_ctx(ctx);
 
             ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, global_ctx, error_callback, &params);
-            for (;;) {
-                int n_bytes = fread(buf, 1, sizeof(buf), f_page);
+            if (ctx != NULL) {
+                for (;;) {
+                    int n_bytes = fread(buf, 1, sizeof(buf), f_page);
 
-                if (n_bytes <= 0)
-                    break;
-                if (jbig2_data_in(ctx, buf, n_bytes))
-                    break;
+                    if (n_bytes <= 0)
+                        break;
+                    if (jbig2_data_in(ctx, buf, n_bytes))
+                        break;
+                }
             }
             fclose(f_page);
             jbig2_global_ctx_free(global_ctx);
@@ -484,7 +489,11 @@
 
             /* work around broken CVision embedded streams */
             if (f_page != NULL)
-                jbig2_complete_page(ctx);
+            {
+                code = jbig2_complete_page(ctx);
+                if (code < 0)
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to complete page");
+            }
 
             if (params.output_file == NULL) {
 #ifdef HAVE_LIBPNG
--- a/pbm2png.c
+++ b/pbm2png.c
@@ -39,7 +39,7 @@
 {
     Jbig2Ctx *ctx;
     Jbig2Image *image;
-    int error;
+    int code;
 
     /* we need a context for the allocators */
     ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL);
@@ -57,10 +57,10 @@
         fprintf(stderr, "converting %dx%d image to png format\n", image->width, image->height);
     }
 
-    error = jbig2_image_write_png_file(image, argv[2]);
-    if (error) {
-        fprintf(stderr, "error writing png file '%s' error %d\n", argv[2], error);
+    code = jbig2_image_write_png_file(image, argv[2]);
+    if (code) {
+        fprintf(stderr, "error writing png file '%s' error %d\n", argv[2], code);
     }
 
-    return (error);
+    return (code);
 }