diff options
-rw-r--r-- | jbig2dec/jbig2.c | 46 | ||||
-rw-r--r-- | jbig2dec/jbig2_generic.c | 13 | ||||
-rw-r--r-- | jbig2dec/jbig2_segment.c | 1 | ||||
-rw-r--r-- | jbig2dec/jbig2_segment.h | 1 |
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, ¶ms, 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; }; |