shithub: jbig2

Download patch

ref: 04004561cba7f208162e121f472f1fdc756423b7
parent: 466be6852e589edac29f9c3dc063df2200daecd4
author: Sebastian Rasmussen <sebras@gmail.com>
date: Sun Jun 24 12:00:30 EDT 2018

jbig2dec: Handle immediate generic regions with unknown height.

--- a/jbig2.c
+++ b/jbig2.c
@@ -292,7 +292,7 @@
         case JBIG2_FILE_RANDOM_HEADERS:
             segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix, &header_size);
             if (segment == NULL)
-                return 0;       /* need more data */
+                return 0; /* need more data */
             ctx->buf_rd_ix += header_size;
 
             if (ctx->n_segments == ctx->n_segments_max) {
@@ -317,8 +317,48 @@
         case JBIG2_FILE_SEQUENTIAL_BODY:
         case JBIG2_FILE_RANDOM_BODIES:
             segment = ctx->segments[ctx->segment_index];
-            if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
-                return 0;       /* need more data */
+
+            /* immediate generic regions may have unknown size */
+            if (segment->data_length == 0xffffffff && (segment->flags & 63) == 38) {
+                byte *s, *e, *p;
+                int mmr;
+                byte mmr_marker[2] = { 0x00, 0x00 };
+                byte arith_marker[2] = { 0xff, 0xac };
+                byte *desired_marker;
+
+                s = p = ctx->buf + ctx->buf_rd_ix;
+                e = ctx->buf + ctx->buf_wr_ix;
+
+                if (e - p < 18)
+                        return 0; /* need more data */
+
+                mmr = p[17] & 1;
+                p += 18;
+                desired_marker = mmr ? mmr_marker : arith_marker;
+
+                /* look for two byte marker */
+                if (e - p < 2)
+                    return 0; /* need more data */
+
+                while (p[0] != desired_marker[0] || p[1] != desired_marker[1]) {
+                    p++;
+                    if (e - p < 2)
+                        return 0; /* need more data */
+                }
+                p += 2;
+
+                /* the marker is followed by a four byte row count */
+                if (e - p < 4)
+                        return 0; /* need more data */
+                segment->rows = jbig2_get_uint32(p);
+                p += 4;
+
+                segment->data_length = p - s;
+                jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "unknown length determined to be %u", segment->data_length);
+            }
+            else if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
+                    return 0; /* need more data */
+
             code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
             ctx->buf_rd_ix += segment->data_length;
             ctx->segment_index++;
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -795,6 +795,7 @@
     Jbig2WordStream *ws = NULL;
     Jbig2ArithState *as = NULL;
     Jbig2ArithCx *GB_stats = NULL;
+    uint32_t height;
 
     /* 7.4.6 */
     if (segment->data_length < 18)
@@ -803,6 +804,14 @@
     jbig2_get_region_segment_info(&rsi, segment_data);
     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "generic region: %d x %d @ (%d, %d), flags = %02x", rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
 
+    /* 7.4.6.4 */
+    height = rsi.height;
+    if (segment->rows != UINT32_MAX) {
+        if (segment->rows > rsi.height)
+            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment contains more rows than stated in header");
+        height = segment->rows;
+    }
+
     /* 7.4.6.2 */
     seg_flags = segment_data[17];
     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "segment flags = %02x", seg_flags);
@@ -831,10 +840,10 @@
     params.USESKIP = 0;
     memcpy(params.gbat, gbat, gbat_bytes);
 
-    image = jbig2_image_new(ctx, rsi.width, rsi.height);
+    image = jbig2_image_new(ctx, rsi.width, height);
     if (image == NULL)
         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);
+    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, height);
 
     if (params.MMR) {
         code = jbig2_decode_generic_mmr(ctx, segment, &params, segment_data + offset, segment->data_length - offset, image);
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -121,6 +121,7 @@
     jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "segment %d is associated with page %d", result->number, result->page_association);
 
     /* 7.2.7 */
+    result->rows = UINT32_MAX;
     result->data_length = jbig2_get_uint32(buf + offset);
     *p_header_size = offset + 4;
 
--- a/jbig2_segment.h
+++ b/jbig2_segment.h
@@ -29,6 +29,7 @@
     size_t data_length;
     int referred_to_segment_count;
     uint32_t *referred_to_segments;
+    uint32_t rows;
     void *result;
 };