shithub: jbig2

Download patch

ref: bef709de120ba435539c4cf7233aa7ec67b9d15a
parent: a780e4ea129d10751af78cc95386cdd2d265d88d
author: Sebastian Rasmussen <sebras@gmail.com>
date: Wed May 23 19:12:16 EDT 2018

jbig2dec: Report warnings if called functions indicate errors.

The first error detected ought to be a fatal error, but when this
error condition is propagated to callers, they should indicate warnings.

--- a/jbig2.c
+++ b/jbig2.c
@@ -324,7 +324,7 @@
             }
             if (code < 0) {
                 ctx->state = JBIG2_FILE_EOF;
-                return code;
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode; treating as end of file");
             }
             break;
         case JBIG2_FILE_EOF:
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -801,11 +801,15 @@
 
     image = jbig2_image_new(ctx, rsi.width, rsi.height);
     if (image == NULL)
-        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to allocate generic image");
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to allocate generic image");
     jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, rsi.height);
 
     if (params.MMR) {
         code = jbig2_decode_generic_mmr(ctx, segment, &params, segment_data + offset, segment->data_length - offset, image);
+        if (code < 0) {
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode MMR-coded generic region");
+            goto cleanup;
+        }
     } else {
         int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
 
@@ -818,22 +822,24 @@
 
         ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
         if (ws == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to allocate ws in jbig2_immediate_generic_region");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to allocate ws in jbig2_immediate_generic_region");
             goto cleanup;
         }
         as = jbig2_arith_new(ctx, ws);
         if (as == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to allocate as in jbig2_immediate_generic_region");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to allocate as in jbig2_immediate_generic_region");
             goto cleanup;
         }
         code = jbig2_decode_generic_region(ctx, segment, &params, as, image, GB_stats);
+        if (code < 0) {
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode generic region");
+            goto cleanup;
+        }
     }
 
-    if (code >= 0)
-        code = 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_FATAL, segment->number, "error while decoding immediate_generic_region");
+        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add result to page");
 
 cleanup:
     jbig2_free(ctx->allocator, as);
--- a/jbig2_halftone.c
+++ b/jbig2_halftone.c
@@ -178,7 +178,7 @@
     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_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error while decoding immediate_generic_region");
     jbig2_image_release(ctx, image);
 
     return hd;
@@ -282,7 +282,7 @@
     for (i = 0; i < GSBPP; ++i) {
         GSPLANES[i] = jbig2_image_new(ctx, GSW, GSH);
         if (GSPLANES[i] == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate %dx%d image for GSPLANES", GSW, GSH);
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate %dx%d image for GSPLANES", GSW, GSH);
             /* free already allocated */
             for (j = i; j > 0;)
                 jbig2_image_release(ctx, GSPLANES[--j]);
@@ -311,13 +311,13 @@
     } else {
         ws = jbig2_word_stream_buf_new(ctx, data, size);
         if (ws == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate ws in jbig2_decode_gray_scale_image");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate ws in jbig2_decode_gray_scale_image");
             goto cleanup;
         }
 
         as = jbig2_arith_new(ctx, ws);
         if (as == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate as in jbig2_decode_gray_scale_image");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate as in jbig2_decode_gray_scale_image");
             goto cleanup;
         }
 
@@ -324,7 +324,7 @@
         code = jbig2_decode_generic_region(ctx, segment, &rparams, as, GSPLANES[GSBPP - 1], GB_stats);
     }
     if (code != 0) {
-        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error decoding GSPLANES for halftone image");
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error decoding GSPLANES for halftone image");
         goto cleanup;
     }
 
@@ -340,7 +340,7 @@
             code = jbig2_decode_generic_region(ctx, segment, &rparams, as, GSPLANES[j], GB_stats);
         }
         if (code != 0) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode GSPLANES for halftone image");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode GSPLANES for halftone image");
             goto cleanup;
         }
 
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -142,7 +142,7 @@
         page->image = jbig2_image_new(ctx, page->width, page->height);
     }
     if (page->image == NULL) {
-        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate buffer for page image");
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate buffer for page image");
     } else {
         /* 8.2 (3) fill the page with the default pixel value */
         jbig2_image_clear(ctx, page->image, (page->flags & 4));
@@ -203,6 +203,9 @@
             code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
             ctx->buf_rd_ix += segment->data_length;
             ctx->segment_index++;
+            if (code < 0) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to parse segment");
+            }
         }
     }
 
@@ -232,10 +235,8 @@
     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of page %d", page_number);
 
     code = jbig2_complete_page(ctx);
-    if (code < 0) {
-        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to complete page");
-        return -1;
-    }
+    if (code < 0)
+        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to complete page");
 
 #ifdef OUTPUT_PBM
     code = jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -445,7 +445,7 @@
 
         ref = jbig2_region_find_referred(ctx, segment);
         if (ref == NULL)
-            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not find reference bitmap");
+            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "could not find reference bitmap");
         /* the reference bitmap is the result of a previous
            intermediate region segment; the reference selection
            rules say to use the first one available, and not to
@@ -475,7 +475,7 @@
 
         image = jbig2_image_new(ctx, rsi.width, rsi.height);
         if (image == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to allocate refinement image");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to allocate refinement image");
             goto cleanup;
         }
         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, rsi.height);
@@ -490,13 +490,13 @@
 
         ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
         if (ws == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate ws in jbig2_refinement_region");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to allocate ws in jbig2_refinement_region");
             goto cleanup;
         }
 
         as = jbig2_arith_new(ctx, ws);
         if (as == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate as in jbig2_refinement_region");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to allocate as in jbig2_refinement_region");
             goto cleanup;
         }
 
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -326,6 +326,10 @@
         } else {
             code = jbig2_arith_int_decode(ctx, IADH, as, &HCDH);
         }
+        if (code < 0) {
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode height class delta");
+            goto cleanup2;
+        }
 
         if (code != 0) {
             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error or OOB decoding height class delta (%d)", code);
@@ -359,7 +363,10 @@
                 code = jbig2_arith_int_decode(ctx, IADW, as, &DW);
             }
             if (code < 0)
+            {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode DW");
                 goto cleanup4;
+            }
 
             /* 6.5.5 (4c.i) */
             if (code == 1) {
@@ -403,12 +410,13 @@
 
                     image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
                     if (image == NULL) {
-                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate image in jbig2_decode_symbol_dict");
+                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate image in jbig2_decode_symbol_dict");
                         goto cleanup4;
                     }
 
                     code = jbig2_decode_generic_region(ctx, segment, &region_params, as, image, GB_stats);
                     if (code < 0) {
+                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode generic region");
                         jbig2_image_release(ctx, image);
                         goto cleanup4;
                     }
@@ -423,6 +431,10 @@
                     } else {
                         code = jbig2_arith_int_decode(ctx, IAAI, as, (int32_t *) &REFAGGNINST);
                     }
+                    if (code < 0) {
+                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode number of symbols in aggregate glyph");
+                        goto cleanup4;
+                    }
                     if (code || (int32_t) REFAGGNINST <= 0) {
                         code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid number of symbols or OOB in aggregate glyph");
                         goto cleanup4;
@@ -445,7 +457,7 @@
                             }
                             refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS + params->SDNUMNEWSYMS);
                             if (refagg_dicts[0] == NULL) {
-                                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "out of memory allocating symbol dictionary");
+                                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory allocating symbol dictionary");
                                 goto cleanup4;
                             }
                             for (i = 0; i < params->SDNUMINSYMS; i++) {
@@ -476,7 +488,7 @@
                                     (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");
+                                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region arith decoder entries");
                                     goto cleanup4;
                                 }
                             } else {
@@ -491,7 +503,7 @@
                                     (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");
+                                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region huffman decoder entries");
                                     goto cleanup4;
                                 }
                             }
@@ -509,7 +521,7 @@
 
                         image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
                         if (image == NULL) {
-                            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "out of memory creating symbol image");
+                            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating symbol image");
                             goto cleanup4;
                         }
 
@@ -517,6 +529,7 @@
                         code = jbig2_decode_text_region(ctx, segment, tparams, (const Jbig2SymbolDict * const *)refagg_dicts,
                                                         n_refagg_dicts, image, data, size, GR_stats, as, ws);
                         if (code < 0) {
+                            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region");
                             jbig2_image_release(ctx, image);
                             goto cleanup4;
                         }
@@ -551,7 +564,7 @@
                         }
 
                         if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0) {
-                            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode data");
+                            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");
                             goto cleanup4;
                         }
 
@@ -565,7 +578,7 @@
 
                         image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
                         if (image == NULL) {
-                            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "out of memory creating symbol image");
+                            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating symbol image");
                             goto cleanup4;
                         }
 
@@ -583,8 +596,10 @@
                         rparams.TPGRON = 0;
                         memcpy(rparams.grat, params->sdrat, 4);
                         code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, image, GR_stats);
-                        if (code < 0)
+                        if (code < 0) {
+                            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
                             goto cleanup4;
+                        }
 
                         SDNEWSYMS->glyphs[NSYMSDECODED] = image;
 
@@ -638,7 +653,7 @@
             int x;
 
             if (code) {
-                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error decoding size of collective bitmap");
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error decoding size of collective bitmap");
                 goto cleanup4;
             }
 
@@ -647,7 +662,7 @@
 
             image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT);
             if (image == NULL) {
-                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not allocate collective bitmap image");
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "could not allocate collective bitmap image");
                 goto cleanup4;
             }
 
@@ -690,7 +705,7 @@
                 rparams.MMR = 1;
                 code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data + jbig2_huffman_offset(hs), BMSIZE, image);
                 if (code) {
-                    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode MMR-coded generic region");
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode MMR-coded generic region");
                     jbig2_image_release(ctx, image);
                     goto cleanup4;
                 }
@@ -706,7 +721,7 @@
 
                 glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
                 if (glyph == NULL) {
-                    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to copy the collective bitmap into symbol dictionary");
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to copy the collective bitmap into symbol dictionary");
                     jbig2_image_release(ctx, image);
                     goto cleanup4;
                 }
@@ -728,7 +743,7 @@
     /* 6.5.10 */
     SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
     if (SDEXSYMS == NULL) {
-        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate symbols exported from symbols dictionary");
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbols exported from symbols dictionary");
         goto cleanup4;
     } else {
         uint32_t i = 0;
@@ -744,6 +759,13 @@
                 exrunlength = jbig2_huffman_get(hs, SBHUFFRSIZE, &code);
             else
                 code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *) &exrunlength);
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode exrunlength for exported symbols");
+                /* skip to the cleanup code and return SDEXSYMS = NULL */
+                jbig2_sd_release(ctx, SDEXSYMS);
+                SDEXSYMS = NULL;
+                break;
+            }
             /* prevent infinite loop */
             zerolength = exrunlength > 0 ? 0 : zerolength + 1;
             if (code || exrunlength > limit - i || zerolength > 4 || (exflag && (exrunlength + j > params->SDNUMEXSYMS))) {
@@ -873,7 +895,7 @@
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
         }
         if (params.SDHUFFDH == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate DH huffman table");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DH huffman table");
             goto cleanup;
         }
 
@@ -899,7 +921,7 @@
             goto cleanup;       /* Jump direct to cleanup to avoid 2 errors being given */
         }
         if (params.SDHUFFDW == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate DW huffman table");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DW huffman table");
             goto cleanup;
         }
 
@@ -917,7 +939,7 @@
             params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
         }
         if (params.SDHUFFBMSIZE == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate BMSIZE huffman table");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate BMSIZE huffman table");
             goto cleanup;
         }
 
@@ -935,7 +957,7 @@
             params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
         }
         if (params.SDHUFFAGGINST == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate REFAGG huffman table");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate REFAGG huffman table");
             goto cleanup;
         }
     }
--- a/jbig2_text.c
+++ b/jbig2_text.c
@@ -108,8 +108,10 @@
         /* parse and build the runlength code huffman table */
         for (index = 0; index < 35; index++) {
             runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4, &code);
-            if (code < 0)
+            if (code < 0) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman runcode lengths");
                 goto cleanup1;
+            }
             runcodelengths[index].RANGELEN = 0;
             runcodelengths[index].RANGELOW = index;
             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d length %d", index, runcodelengths[index].PREFLEN);
@@ -119,7 +121,7 @@
         runcodeparams.n_lines = 35;
         runcodes = jbig2_build_huffman_table(ctx, &runcodeparams);
         if (runcodes == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error constructing symbol id runcode table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error constructing symbol id runcode table");
             goto cleanup1;
         }
 
@@ -132,11 +134,14 @@
         index = 0;
         while (index < SBNUMSYMS) {
             code = jbig2_huffman_get(hs, runcodes, &err);
-            if (err != 0 || code < 0 || code >= 35) {
-                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error reading symbol ID huffman table");
-                code = err ? err : -1;
+            if (err < 0) {
+                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error reading symbol ID huffman table");
                 goto cleanup1;
             }
+            if (code < 0 || code >= 35) {
+                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol ID huffman table out of range");
+                goto cleanup1;
+            }
 
             if (code < 32) {
                 len = code;
@@ -158,8 +163,10 @@
                     range = jbig2_huffman_get_bits(hs, 3, &err) + 3;
                 else if (code == 34)
                     range = jbig2_huffman_get_bits(hs, 7, &err) + 11;
-                if (err < 0)
+                if (err < 0) {
+                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman code");
                     goto cleanup1;
+                }
             }
             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d at index %d (length %d range %d)", code, index, len, range);
             if (index + range > SBNUMSYMS) {
@@ -193,7 +200,7 @@
         jbig2_release_huffman_table(ctx, runcodes);
 
         if (SBSYMCODES == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not construct Symbol ID huffman table");
+            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "could not construct Symbol ID huffman table");
             jbig2_huffman_free(ctx, hs);
             return ((code != 0) ? code : -1);
         }
@@ -262,6 +269,10 @@
                 } else {
                     code = jbig2_arith_int_decode(ctx, params->IADS, as, &IDS);
                 }
+                if (code < 0) {
+                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance S coordinate");
+                    goto cleanup2;
+                }
                 if (code) {
                     /* decoded an OOB, reached end of strip */
                     break;
@@ -290,7 +301,7 @@
                 code = jbig2_arith_iaid_decode(ctx, params->IAID, as, (int *)&ID);
             }
             if (code < 0) {
-                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");
+                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");
                 goto cleanup2;
             }
             if (ID >= SBNUMSYMS) {
@@ -354,7 +365,7 @@
 
                 if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0) {
                     jbig2_image_release(ctx, IB);
-                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode data");
+                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");
                     goto cleanup2;
                 }
 
@@ -371,7 +382,7 @@
                     if (params->SBHUFF) {
                         jbig2_release_huffman_table(ctx, SBSYMCODES);
                     }
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "couldn't allocate reference image");
+                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "couldn't allocate reference image");
                 }
                 jbig2_image_clear(ctx, refimage, 0x00);
 
@@ -602,7 +613,7 @@
             break;
         }
         if (params.SBHUFFFS == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified FS huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified FS huffman table");
             goto cleanup1;
         }
 
@@ -627,7 +638,7 @@
             break;
         }
         if (params.SBHUFFDS == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified DS huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified DS huffman table");
             goto cleanup1;
         }
 
@@ -652,7 +663,7 @@
             break;
         }
         if (params.SBHUFFDT == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified DT huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified DT huffman table");
             goto cleanup1;
         }
 
@@ -679,7 +690,7 @@
             break;
         }
         if (params.SBHUFFRDW == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified RDW huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDW huffman table");
             goto cleanup1;
         }
 
@@ -706,7 +717,7 @@
             break;
         }
         if (params.SBHUFFRDH == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified RDH huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDH huffman table");
             goto cleanup1;
         }
 
@@ -733,7 +744,7 @@
             break;
         }
         if (params.SBHUFFRDX == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified RDX huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDX huffman table");
             goto cleanup1;
         }
 
@@ -760,7 +771,7 @@
             break;
         }
         if (params.SBHUFFRDY == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified RDY huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDY huffman table");
             goto cleanup1;
         }
 
@@ -779,7 +790,7 @@
             break;
         }
         if (params.SBHUFFRSIZE == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate text region specified RSIZE huffman table");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RSIZE huffman table");
             goto cleanup1;
         }
 
@@ -833,7 +844,7 @@
 
     image = jbig2_image_new(ctx, region_info.width, region_info.height);
     if (image == NULL) {
-        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "couldn't allocate text region image");
+        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "couldn't allocate text region image");
         goto cleanup2;
     }
 
@@ -841,13 +852,13 @@
         goto too_short;
     ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
     if (ws == NULL) {
-        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "couldn't allocate ws in text region image");
+        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "couldn't allocate ws in text region image");
         goto cleanup2;
     }
 
     as = jbig2_arith_new(ctx, ws);
     if (as == NULL) {
-        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "couldn't allocate as in text region image");
+        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "couldn't allocate as in text region image");
         goto cleanup2;
     }
 
@@ -864,7 +875,7 @@
         params.IADS = jbig2_arith_int_ctx_new(ctx);
         params.IAIT = jbig2_arith_int_ctx_new(ctx);
         if (params.IADT == NULL || params.IAFS == NULL || params.IADS == NULL || params.IAIT == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "couldn't allocate text region image data");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "couldn't allocate text region image data");
             goto cleanup3;
         }
 
@@ -879,7 +890,7 @@
         params.IARDY = jbig2_arith_int_ctx_new(ctx);
         if (params.IAID == NULL || params.IARI == NULL ||
             params.IARDW == NULL || params.IARDH == NULL || params.IARDX == NULL || params.IARDY == NULL) {
-            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "couldn't allocate text region image data");
+            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "couldn't allocate text region image data");
             goto cleanup4;
         }
     }
@@ -888,7 +899,7 @@
                                     (const Jbig2SymbolDict * const *)dicts, n_dicts, image,
                                     segment_data + offset, segment->data_length - offset, GR_stats, as, ws);
     if (code < 0) {
-        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode text region image data");
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region image data");
         goto cleanup4;
     }