summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jbig2dec/jbig2.c46
-rw-r--r--jbig2dec/jbig2_generic.c13
-rw-r--r--jbig2dec/jbig2_segment.c1
-rw-r--r--jbig2dec/jbig2_segment.h1
4 files changed, 56 insertions, 5 deletions
diff --git a/jbig2dec/jbig2.c b/jbig2dec/jbig2.c
index 2152859bd..c01bac3a3 100644
--- a/jbig2dec/jbig2.c
+++ b/jbig2dec/jbig2.c
@@ -292,7 +292,7 @@ jbig2_data_in(Jbig2Ctx *ctx, const unsigned char *data, size_t size)
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 @@ jbig2_data_in(Jbig2Ctx *ctx, const unsigned char *data, size_t size)
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++;
diff --git a/jbig2dec/jbig2_generic.c b/jbig2dec/jbig2_generic.c
index 89351ece6..a3a89415c 100644
--- a/jbig2dec/jbig2_generic.c
+++ b/jbig2dec/jbig2_generic.c
@@ -795,6 +795,7 @@ jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte
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_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte
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 @@ jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte
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);
diff --git a/jbig2dec/jbig2_segment.c b/jbig2dec/jbig2_segment.c
index 81e0b2496..c42a7c1c6 100644
--- a/jbig2dec/jbig2_segment.c
+++ b/jbig2dec/jbig2_segment.c
@@ -121,6 +121,7 @@ jbig2_parse_segment_header(Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size, size_t
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;
diff --git a/jbig2dec/jbig2_segment.h b/jbig2dec/jbig2_segment.h
index 583b13682..0b61b6586 100644
--- a/jbig2dec/jbig2_segment.h
+++ b/jbig2dec/jbig2_segment.h
@@ -29,6 +29,7 @@ struct _Jbig2Segment {
size_t data_length;
int referred_to_segment_count;
uint32_t *referred_to_segments;
+ uint32_t rows;
void *result;
};