ref: 1fddee262691d23dc283965c0dbe0e0de2c85bf9
parent: f680c2d09d76172f7adee998608a8df0b8d2828c
author: Shailesh Mistry <[email protected]>
date: Tue Nov 29 15:33:16 EST 2011
Bug 691267: jbig2dec needs to check malloc() return values This fix checks all return paths to ensure that the appropriate error is returned on failure from any malloc() call within jbig2dec.
--- a/jbig2.c
+++ b/jbig2.c
@@ -143,11 +143,24 @@
result->n_segments = 0;
result->n_segments_max = 16;
result->segments = jbig2_new(result, Jbig2Segment*, result->n_segments_max);
+ if (result->segments == NULL) {
+ error_callback(error_callback_data, "initial segments allocation failed!",
+ JBIG2_SEVERITY_FATAL, -1);
+ jbig2_free(allocator, result);
+ return result;
+ }
result->segment_index = 0;
result->current_page = 0;
result->max_page_index = 4;
result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
+ if (result->pages == NULL) {
+ error_callback(error_callback_data, "initial pages allocation failed!",
+ JBIG2_SEVERITY_FATAL, -1);
+ jbig2_free(allocator, result->segments);
+ jbig2_free(allocator, result);
+ return result;
+ }
{
int index;
for (index = 0; index < result->max_page_index; index++) {
@@ -216,6 +229,11 @@
buf_size <<= 1;
while (buf_size < size);
ctx->buf = jbig2_new(ctx, byte, buf_size);
+ if (ctx->buf == NULL)
+ {
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate ctx->buf in jbig2_data_in");
+ }
ctx->buf_size = buf_size;
ctx->buf_rd_ix = 0;
ctx->buf_wr_ix = 0;
@@ -237,6 +255,11 @@
buf_size <<= 1;
while (buf_size < ctx->buf_wr_ix - ctx->buf_rd_ix + size);
buf = jbig2_new(ctx, byte, buf_size);
+ if (buf == NULL)
+ {
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate buf in jbig2_data_in");
+ }
memcpy(buf, ctx->buf + ctx->buf_rd_ix,
ctx->buf_wr_ix - ctx->buf_rd_ix);
jbig2_free(ctx->allocator, ctx->buf);
@@ -430,6 +453,12 @@
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
{
Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
+ if (result == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate Jbig2WordStreamBuf in jbig2_word_stream_buf_new");
+ return NULL;
+ }
result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
result->data = data;
--- a/jbig2_arith.c
+++ b/jbig2_arith.c
@@ -181,6 +181,12 @@
Jbig2ArithState *result;
result = jbig2_new(ctx, Jbig2ArithState, 1);
+ if (result == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate Jbig2ArithState in jbig2_arith_new");
+ return result;
+ }
result->ws = ws;
--- a/jbig2_arith_iaid.c
+++ b/jbig2_arith_iaid.c
@@ -46,9 +46,24 @@
Jbig2ArithIaidCtx *result = jbig2_new(ctx, Jbig2ArithIaidCtx, 1);
int ctx_size = 1 << SBSYMCODELEN;
+ if (result == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate storage in jbig2_arith_iaid_ctx_new");
+ return result;
+ }
+
result->SBSYMCODELEN = SBSYMCODELEN;
result->IAIDx = jbig2_new(ctx, Jbig2ArithCx, ctx_size);
- memset(result->IAIDx, 0, ctx_size);
+ if (result->IAIDx != NULL)
+ {
+ memset(result->IAIDx, 0, ctx_size);
+ }
+ else
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate symbol ID storage in jbig2_arith_iaid_ctx_new");
+ }
return result;
}
@@ -86,6 +101,9 @@
void
jbig2_arith_iaid_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *iax)
{
- jbig2_free(ctx->allocator, iax->IAIDx);
- jbig2_free(ctx->allocator, iax);
+ if (iax != NULL)
+ {
+ jbig2_free(ctx->allocator, iax->IAIDx);
+ jbig2_free(ctx->allocator, iax);
+ }
}
--- a/jbig2_arith_int.c
+++ b/jbig2_arith_int.c
@@ -40,7 +40,15 @@
{
Jbig2ArithIntCtx *result = jbig2_new(ctx, Jbig2ArithIntCtx, 1);
- memset(result->IAx, 0, sizeof(result->IAx));
+ if (result == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate Jbig2ArithIntCtx in jbig2_arith_int_ctx_new");
+ }
+ else
+ {
+ memset(result->IAx, 0, sizeof(result->IAx));
+ }
return result;
}
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -769,10 +769,10 @@
int offset;
int gbat_bytes = 0;
Jbig2GenericRegionParams params;
- int code;
- Jbig2Image *image;
- Jbig2WordStream *ws;
- Jbig2ArithState *as;
+ int code = 0;
+ Jbig2Image *image = NULL;
+ Jbig2WordStream *ws = NULL;
+ Jbig2ArithState *as = NULL;
Jbig2ArithCx *GB_stats = NULL;
/* 7.4.6 */
@@ -816,7 +816,7 @@
image = jbig2_image_new(ctx, rsi.width, rsi.height);
if (image == NULL)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ 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",
@@ -825,29 +825,46 @@
if (params.MMR)
{
code = jbig2_decode_generic_mmr(ctx, segment, ¶ms,
- segment_data + offset, segment->data_length - offset,
- image);
+ segment_data + offset, segment->data_length - offset, image);
}
else
{
int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GB_stats == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "unable to allocate GB_stats in jbig2_immediate_generic_region");
+ goto cleanup;
+ }
memset(GB_stats, 0, stats_size);
- ws = jbig2_word_stream_buf_new(ctx,
- segment_data + offset,
- segment->data_length - offset);
+ 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");
+ 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");
+ goto cleanup;
+ }
code = jbig2_decode_generic_region(ctx, segment, ¶ms,
as, image, GB_stats);
- jbig2_free(ctx->allocator, as);
- jbig2_word_stream_buf_free(ctx, ws);
-
- jbig2_free(ctx->allocator, GB_stats);
}
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
image, rsi.x, rsi.y, JBIG2_COMPOSE_OR);
+
+cleanup:
+ jbig2_free(ctx->allocator, as);
+ jbig2_word_stream_buf_free(ctx, ws);
+ jbig2_free(ctx->allocator, GB_stats);
jbig2_image_release(ctx, image);
return code;
--- a/jbig2_halftone.c
+++ b/jbig2_halftone.c
@@ -79,6 +79,8 @@
if (new != NULL) {
new->patterns = jbig2_new(ctx, Jbig2Image*, N);
if (new->patterns == NULL) {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate pattern in collective bitmap dictionary");
jbig2_free(ctx->allocator, new);
return NULL;
}
@@ -91,7 +93,7 @@
new->patterns[i] = jbig2_image_new(ctx, HPW, HPH);
if (new->patterns[i] == NULL) {
int j;
- jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
"failed to allocate pattern element image");
for (j = 0; j < i; j++)
jbig2_free(ctx->allocator, new->patterns[j]);
@@ -105,6 +107,11 @@
-i * HPW, 0, JBIG2_COMPOSE_REPLACE);
}
}
+ else
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate collective bitmap dictionary");
+ }
return new;
}
@@ -147,16 +154,16 @@
Jbig2ArithCx *GB_stats)
{
Jbig2PatternDict *hd = NULL;
- Jbig2Image *image;
+ Jbig2Image *image = NULL;
Jbig2GenericRegionParams rparams;
- int code;
+ int code = 0;
/* allocate the collective image */
image = jbig2_image_new(ctx,
params->HDPW * (params->GRAYMAX + 1), params->HDPH);
if (image == NULL) {
- jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "failed to allocate collective bitmap for halftone dict!");
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate collective bitmap for halftone dict!");
return NULL;
}
@@ -175,22 +182,32 @@
rparams.gbat[7] = -2;
if (params->HDMMR) {
- code = jbig2_decode_generic_mmr(ctx, segment, &rparams,
- data, size, image);
+ code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data, size, image);
} else {
Jbig2WordStream *ws = jbig2_word_stream_buf_new(ctx, data, size);
- Jbig2ArithState *as = jbig2_arith_new(ctx, ws);
+ if (ws != NULL)
+ {
+ Jbig2ArithState *as = jbig2_arith_new(ctx, ws);
+ if (as != NULL)
+ {
+ code = jbig2_decode_generic_region(ctx, segment, &rparams,
+ as, image, GB_stats);
+ }
+ else
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage for as in halftone dict!");
+ }
- code = jbig2_decode_generic_region(ctx, segment, &rparams,
- as, image, GB_stats);
-
- jbig2_free(ctx->allocator, as);
- jbig2_word_stream_buf_free(ctx, ws);
+ jbig2_free(ctx->allocator, as);
+ jbig2_word_stream_buf_free(ctx, ws);
+ }
+ else
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage for ws in halftone dict!");
+ }
}
- if (code != 0) {
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
- "error decoding collective pattern dictionary bitmap!");
- }
hd = jbig2_hd_new(ctx, params, image);
jbig2_image_release(ctx, image);
@@ -240,6 +257,12 @@
/* allocate and zero arithmetic coding stats */
int stats_size = jbig2_generic_stats_size(ctx, params.HDTEMPLATE);
GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GB_stats == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate GB_stats in pattern dictionary");
+ return NULL;
+ }
memset(GB_stats, 0, stats_size);
}
@@ -269,7 +292,9 @@
{
int code = 0;
- /* todo: implement */
+ code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "decode a halftone region not yet implemented");
+
return code;
}
@@ -282,9 +307,9 @@
int offset = 0;
Jbig2RegionSegmentInfo region_info;
Jbig2HalftoneRegionParams params;
- Jbig2Image *image;
- Jbig2ArithCx *GB_stats;
- int code;
+ Jbig2Image *image = NULL;
+ Jbig2ArithCx *GB_stats = NULL;
+ int code = 0;
/* 7.4.5.1 */
if (segment->data_length < 17) goto too_short;
@@ -345,13 +370,21 @@
/* allocate and zero arithmetic coding stats */
int stats_size = jbig2_generic_stats_size(ctx, params.HTEMPLATE);
GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GB_stats == NULL)
+ {
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate GB_stats in halftone region");
+ }
memset(GB_stats, 0, stats_size);
}
image = jbig2_image_new(ctx, region_info.width, region_info.height);
if (image == NULL)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "unable to allocate halftone image");
+ {
+ jbig2_free(ctx->allocator, GB_stats);
+ return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "unable to allocate halftone image");
+ }
code = jbig2_decode_halftone_region(ctx, segment, ¶ms,
segment_data + offset, segment->data_length - offset,
--- a/jbig2_huffman.c
+++ b/jbig2_huffman.c
@@ -59,7 +59,7 @@
Jbig2HuffmanState *
jbig2_huffman_new (Jbig2Ctx *ctx, Jbig2WordStream *ws)
{
- Jbig2HuffmanState *result;
+ Jbig2HuffmanState *result = NULL;
result = jbig2_new(ctx, Jbig2HuffmanState, 1);
@@ -68,8 +68,10 @@
result->offset_bits = 0;
result->this_word = ws->get_next_word (ws, 0);
result->next_word = ws->get_next_word (ws, 4);
-
result->ws = ws;
+ } else {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate new huffman coding state");
}
return result;
@@ -370,8 +372,20 @@
max_j = 1 << log_table_size;
result = jbig2_new(ctx, Jbig2HuffmanTable, 1);
+ if (result == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "couldn't allocate result storage in jbig2_build_huffman_table");
+ return NULL;
+ }
result->log_table_size = log_table_size;
entries = jbig2_new(ctx, Jbig2HuffmanEntry, max_j);
+ if (entries == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "couldn't allocate entries storage in jbig2_build_huffman_table");
+ return NULL;
+ }
result->entries = entries;
LENCOUNT[0] = 0;
--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -36,7 +36,7 @@
image = jbig2_new(ctx, Jbig2Image, 1);
if (image == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
- "could not allocate image structure");
+ "could not allocate image structure in jbig2_image_new");
return NULL;
}
@@ -43,8 +43,8 @@
stride = ((width - 1) >> 3) + 1; /* generate a byte-aligned stride */
image->data = jbig2_new(ctx, uint8_t, stride*height);
if (image->data == NULL) {
- jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
- "could not allocate image data buffer! [%d bytes]\n", stride*height);
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "could not allocate image data buffer! [%d bytes]\n", stride*height);
jbig2_free(ctx->allocator, image);
return NULL;
}
--- a/jbig2_metadata.c
+++ b/jbig2_metadata.c
@@ -37,9 +37,14 @@
md->keys = jbig2_new(ctx, char*, md->max_entries);
md->values = jbig2_new(ctx, char*, md->max_entries);
if (md->keys == NULL || md->values == NULL) {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate storage for metadata keys/values");
jbig2_metadata_free(ctx, md);
md = NULL;
}
+ } else {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate storage for metadata");
}
return md;
}
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -145,7 +145,7 @@
page->image = jbig2_image_new(ctx, page->width, page->height);
}
if (page->image == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ 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 */
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -393,11 +393,11 @@
params.DX = 0;
params.DY = 0;
{
- Jbig2WordStream *ws;
- Jbig2ArithState *as;
+ Jbig2WordStream *ws = NULL;
+ Jbig2ArithState *as = NULL;
Jbig2ArithCx *GR_stats = NULL;
int stats_size;
- Jbig2Image *image;
+ Jbig2Image *image = NULL;
int code;
image = jbig2_image_new(ctx, rsi.width, rsi.height);
@@ -410,18 +410,34 @@
stats_size = params.GRTEMPLATE ? 1 << 10 : 1 << 13;
GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GR_stats == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate GR-stats in jbig2_refinement_region");
+ goto cleanup;
+ }
memset(GR_stats, 0, stats_size);
ws = jbig2_word_stream_buf_new(ctx, segment_data + offset,
segment->data_length - offset);
+ if (ws == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate ws in jbig2_refinement_region");
+ goto cleanup;
+ }
+
as = jbig2_arith_new(ctx, ws);
+ if (as == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate as in jbig2_refinement_region");
+ goto cleanup;
+ }
+
code = jbig2_decode_refinement_region(ctx, segment, ¶ms,
as, image, GR_stats);
- jbig2_free(ctx->allocator, as);
- jbig2_word_stream_buf_free(ctx, ws);
- jbig2_free(ctx->allocator, GR_stats);
-
if ((segment->flags & 63) == 40) {
/* intermediate region. save the result for later */
segment->result = image;
@@ -434,6 +450,11 @@
image, rsi.x, rsi.y, rsi.op);
jbig2_image_release(ctx, image);
}
+
+cleanup:
+ jbig2_free(ctx->allocator, as);
+ jbig2_word_stream_buf_free(ctx, ws);
+ jbig2_free(ctx->allocator, GR_stats);
}
return 0;
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -44,6 +44,12 @@
return NULL;
result = jbig2_new(ctx, Jbig2Segment, 1);
+ if (result == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate segment in jbig2_parse_segment_header");
+ return result;
+ }
/* 7.2.2 */
result->number = jbig2_get_uint32(buf);
@@ -85,6 +91,13 @@
referred_to_segments = jbig2_new(ctx, uint32_t,
referred_to_segment_count * referred_to_segment_size);
+ if (referred_to_segments == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "could not allocate referred_to_segments "
+ "in jbig2_parse_segment_header");
+ return NULL;
+ }
for (i = 0; i < referred_to_segment_count; i++) {
referred_to_segments[i] =
@@ -197,18 +210,15 @@
int jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment,
const uint8_t *segment_data)
{
- uint32_t type;
- bool reserved, dependent, necessary;
+ uint32_t type = jbig2_get_uint32(segment_data);
+ bool reserved = type & 0x20000000;
+ /* bool dependent = type & 0x40000000; (NYI) */
+ bool necessary = type & 0x80000000;
- type = jbig2_get_uint32(segment_data);
-
- reserved = type & 0x20000000;
- dependent = type & 0x40000000;
- necessary = type & 0x80000000;
-
if (necessary && !reserved) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
- "extension segment is marked 'necessary' but not 'reservered' contrary to spec");
+ "extension segment is marked 'necessary' but "
+ "not 'reservered' contrary to spec");
}
switch (type) {
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -96,6 +96,8 @@
new->glyphs = jbig2_new(ctx, Jbig2Image*, n_symbols);
new->n_symbols = n_symbols;
} else {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "unable to allocate new empty symbol dict");
return NULL;
}
@@ -102,6 +104,8 @@
if (new->glyphs != NULL) {
memset(new->glyphs, 0, n_symbols*sizeof(Jbig2Image*));
} else {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "unable to allocate glyphs for new empty symbol dict");
jbig2_free(ctx->allocator, new);
return NULL;
}
@@ -157,6 +161,13 @@
int dindex = 0;
dicts = jbig2_new(ctx, Jbig2SymbolDict*, n_dicts);
+ if (dicts == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate referred list of symbol dictionaries");
+ return NULL;
+ }
+
for (index = 0; index < segment->referred_to_segment_count; index++) {
rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
if (rsegment && ((rsegment->flags & 63) == 0)) {
@@ -195,6 +206,9 @@
for (i = 0; i < n_dicts; i++)
for (j = 0; j < dicts[i]->n_symbols; j++)
new->glyphs[k++] = jbig2_image_clone(ctx, dicts[i]->glyphs[j]);
+ } else {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
+ "failed to allocate new symbol dictionary");
}
return new;
@@ -212,8 +226,8 @@
Jbig2ArithCx *GB_stats,
Jbig2ArithCx *GR_stats)
{
- Jbig2SymbolDict *SDNEWSYMS;
- Jbig2SymbolDict *SDEXSYMS;
+ Jbig2SymbolDict *SDNEWSYMS = NULL;
+ Jbig2SymbolDict *SDEXSYMS = NULL;
int32_t HCHEIGHT;
uint32_t NSYMSDECODED;
int32_t SYMWIDTH, TOTWIDTH;
@@ -232,7 +246,7 @@
Jbig2ArithIntCtx *IARDX = NULL;
Jbig2ArithIntCtx *IARDY = NULL;
int code = 0;
- Jbig2SymbolDict **refagg_dicts;
+ Jbig2SymbolDict **refagg_dicts = NULL;
int n_refagg_dicts = 1;
Jbig2TextRegionParams *tparams = NULL;
@@ -242,6 +256,12 @@
NSYMSDECODED = 0;
ws = jbig2_word_stream_buf_new(ctx, data, size);
+ if (ws == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage in jbig2_decode_symbol_dict");
+ return NULL;
+ }
if (!params->SDHUFF) {
as = jbig2_arith_new(ctx, ws);
@@ -249,30 +269,53 @@
IADW = jbig2_arith_int_ctx_new(ctx);
IAEX = jbig2_arith_int_ctx_new(ctx);
IAAI = jbig2_arith_int_ctx_new(ctx);
+ if ((as == NULL) || (IADH == NULL) || (IADW == NULL) ||
+ (IAEX == NULL) || (IAAI == NULL))
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage for symbol bitmap");
+ goto cleanup1;
+ }
if (params->SDREFAGG) {
- int tmp = params->SDINSYMS->n_symbols + params->SDNUMNEWSYMS;
- for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < tmp; SBSYMCODELEN++);
- IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
- IARDX = jbig2_arith_int_ctx_new(ctx);
- IARDY = jbig2_arith_int_ctx_new(ctx);
+ int tmp = params->SDINSYMS->n_symbols + params->SDNUMNEWSYMS;
+ for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < tmp; SBSYMCODELEN++);
+ IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
+ IARDX = jbig2_arith_int_ctx_new(ctx);
+ IARDY = jbig2_arith_int_ctx_new(ctx);
+ if ((IAID == NULL) || (IARDX == NULL) || (IARDY == NULL))
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage for symbol bitmap");
+ goto cleanup2;
+ }
}
} else {
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
- "huffman coded symbol dictionary");
+ "huffman coded symbol dictionary");
hs = jbig2_huffman_new(ctx, ws);
- SDHUFFRDX = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_O);
+ SDHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
+ if ( (hs == NULL) || (SDHUFFRDX == NULL))
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage for symbol bitmap");
+ goto cleanup2;
+ }
if (!params->SDREFAGG) {
SDNEWSYMWIDTHS = jbig2_new(ctx, uint32_t, params->SDNUMNEWSYMS);
if (SDNEWSYMWIDTHS == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "could not allocate storage for symbol widths");
- return NULL;
+ "could not allocate storage for symbol widths");
+ goto cleanup2;
}
}
}
SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
+ if (SDNEWSYMS == NULL) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "could not allocate storage for symbols");
+ goto cleanup2;
+ }
/* 6.5.5 (4a) */
while (NSYMSDECODED < params->SDNUMNEWSYMS) {
@@ -297,10 +340,9 @@
HCFIRSTSYM = NSYMSDECODED;
if (HCHEIGHT < 0) {
- /* todo: mem cleanup */
- code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "Invalid HCHEIGHT value");
- return NULL;
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "Invalid HCHEIGHT value");
+ goto cleanup2;
}
#ifdef JBIG2_DEBUG
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
@@ -312,17 +354,17 @@
for (;;) {
/* check for broken symbol table */
if (NSYMSDECODED > params->SDNUMNEWSYMS)
- {
- /* todo: mem cleanup? */
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
- "No OOB signalling end of height class %d", HCHEIGHT);
- break;
- }
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "No OOB signalling end of height class %d", HCHEIGHT);
+ goto cleanup4;
+ }
/* 6.5.7 */
if (params->SDHUFF) {
DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
} else {
code = jbig2_arith_int_decode(IADW, as, &DW);
+ if (code < 0) goto cleanup4;
}
/* 6.5.5 (4c.i) */
@@ -334,11 +376,10 @@
SYMWIDTH = SYMWIDTH + DW;
TOTWIDTH = TOTWIDTH + SYMWIDTH;
if (SYMWIDTH < 0) {
- /* todo: mem cleanup */
- code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "Invalid SYMWIDTH value (%d) at symbol %d", SYMWIDTH, NSYMSDECODED+1);
- return NULL;
- }
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "Invalid SYMWIDTH value (%d) at symbol %d", SYMWIDTH, NSYMSDECODED+1);
+ goto cleanup4;
+ }
#ifdef JBIG2_DEBUG
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"SYMWIDTH = %d TOTWIDTH = %d", SYMWIDTH, TOTWIDTH);
@@ -364,16 +405,21 @@
memcpy(region_params.gbat, params->sdat, sdat_bytes);
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");
+ goto cleanup4;
+ }
code = jbig2_decode_generic_region(ctx, segment, ®ion_params,
- as, image, GB_stats);
- /* todo: handle errors */
+ as, image, GB_stats);
+ if (code < 0) goto cleanup4;
- SDNEWSYMS->glyphs[NSYMSDECODED] = image;
-
+ SDNEWSYMS->glyphs[NSYMSDECODED] = image;
} else {
- /* 6.5.8.2 refinement/aggregate symbol */
- uint32_t REFAGGNINST;
+ /* 6.5.8.2 refinement/aggregate symbol */
+ uint32_t REFAGGNINST;
if (params->SDHUFF) {
REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
@@ -382,8 +428,8 @@
}
if (code || (int32_t)REFAGGNINST <= 0) {
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "invalid number of symbols or OOB in aggregate glyph");
- return NULL;
+ "invalid number of symbols or OOB in aggregate glyph");
+ goto cleanup4;
}
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
@@ -402,7 +448,7 @@
if (refagg_dicts == NULL) {
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Out of memory allocating dictionary array");
- return NULL;
+ goto cleanup4;
}
refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS + params->SDNUMNEWSYMS);
if (refagg_dicts[0] == NULL) {
@@ -409,7 +455,7 @@
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Out of memory allocating symbol dictionary");
jbig2_free(ctx->allocator, refagg_dicts);
- return NULL;
+ goto cleanup4;
}
refagg_dicts[0]->n_symbols = params->SDNUMINSYMS + params->SDNUMNEWSYMS;
for (i=0;i < params->SDNUMINSYMS;i++)
@@ -423,9 +469,9 @@
"Out of memory creating text region params");
jbig2_sd_release(ctx, refagg_dicts[0]);
jbig2_free(ctx->allocator, refagg_dicts);
- return NULL;
+ goto cleanup4;
}
- if (!params->SDHUFF) {
+ if (!params->SDHUFF) {
/* Values from Table 17, section 6.5.8.2 (2) */
tparams->IADT = jbig2_arith_int_ctx_new(ctx);
tparams->IAFS = jbig2_arith_int_ctx_new(ctx);
@@ -468,14 +514,14 @@
}
tparams->SBNUMINSTANCES = REFAGGNINST;
- image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
+ 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");
- jbig2_free(ctx->allocator, tparams);
- jbig2_sd_release(ctx, refagg_dicts[0]);
- jbig2_free(ctx->allocator, refagg_dicts);
- return NULL;
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "Out of memory creating symbol image");
+ jbig2_free(ctx->allocator, tparams);
+ jbig2_sd_release(ctx, refagg_dicts[0]);
+ jbig2_free(ctx->allocator, refagg_dicts);
+ goto cleanup4;
}
/* multiple symbols are handled as a text region */
@@ -504,16 +550,21 @@
}
if (ID >= ninsyms+NSYMSDECODED) {
- code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "refinement references unknown symbol %d", ID);
- return NULL;
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "refinement references unknown symbol %d", ID);
+ goto cleanup4;
}
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
- "symbol is a refinement of id %d with the refinement applied at (%d,%d)",
- ID, RDX, RDY);
+ "symbol is a refinement of id %d with the "
+ "refinement applied at (%d,%d)", ID, RDX, RDY);
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");
+ goto cleanup4;
+ }
/* Table 18 */
rparams.GRTEMPLATE = params->SDRTEMPLATE;
@@ -528,7 +579,6 @@
&rparams, as, image, GR_stats);
SDNEWSYMS->glyphs[NSYMSDECODED] = image;
-
}
}
@@ -573,8 +623,7 @@
if (code || (BMSIZE < 0)) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"error decoding size of collective bitmap!");
- /* todo: memory cleanup */
- return NULL;
+ goto cleanup4;
}
/* skip any bits before the next byte boundary */
@@ -584,8 +633,7 @@
if (image == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"could not allocate collective bitmap image!");
- /* todo: memory cleanup */
- return NULL;
+ goto cleanup4;
}
if (BMSIZE == 0) {
@@ -619,8 +667,7 @@
if (code) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"error decoding MMR bitmap image!");
- /* todo: memory cleanup */
- return NULL;
+ goto cleanup4;
}
}
@@ -632,8 +679,13 @@
for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) {
Jbig2Image *glyph;
glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
- jbig2_image_compose(ctx, glyph, image,
- -x, 0, JBIG2_COMPOSE_REPLACE);
+ if (glyph == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to copy the collective bitmap into symbol dictionary");
+ goto cleanup4;
+ }
+ jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
x += SDNEWSYMWIDTHS[j];
SDNEWSYMS->glyphs[j] = glyph;
}
@@ -642,42 +694,16 @@
} /* end of symbol decode loop */
- if (tparams != NULL)
- {
- if (!params->SDHUFF)
- {
- jbig2_arith_int_ctx_free(ctx, tparams->IADT);
- jbig2_arith_int_ctx_free(ctx, tparams->IAFS);
- jbig2_arith_int_ctx_free(ctx, tparams->IADS);
- jbig2_arith_int_ctx_free(ctx, tparams->IAIT);
- jbig2_arith_iaid_ctx_free(ctx, tparams->IAID);
- jbig2_arith_int_ctx_free(ctx, tparams->IARI);
- jbig2_arith_int_ctx_free(ctx, tparams->IARDW);
- jbig2_arith_int_ctx_free(ctx, tparams->IARDH);
- jbig2_arith_int_ctx_free(ctx, tparams->IARDX);
- jbig2_arith_int_ctx_free(ctx, tparams->IARDY);
- }
- else
- {
- jbig2_release_huffman_table(ctx, tparams->SBHUFFFS);
- jbig2_release_huffman_table(ctx, tparams->SBHUFFDS);
- jbig2_release_huffman_table(ctx, tparams->SBHUFFDT);
- jbig2_release_huffman_table(ctx, tparams->SBHUFFRDX);
- jbig2_release_huffman_table(ctx, tparams->SBHUFFRDY);
- jbig2_release_huffman_table(ctx, tparams->SBHUFFRDW);
- jbig2_release_huffman_table(ctx, tparams->SBHUFFRDH);
- }
- jbig2_free(ctx->allocator, tparams);
- tparams = NULL;
- jbig2_sd_release(ctx, refagg_dicts[0]);
- jbig2_free(ctx->allocator, refagg_dicts);
- }
-
- jbig2_free(ctx->allocator, GB_stats);
-
/* 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");
+ goto cleanup4;
+ }
+ else
+ {
int i = 0;
int j = 0;
int k, m, exflag = 0;
@@ -714,28 +740,56 @@
}
}
- jbig2_sd_release(ctx, SDNEWSYMS);
-
- if (!params->SDHUFF) {
- jbig2_arith_int_ctx_free(ctx, IADH);
- jbig2_arith_int_ctx_free(ctx, IADW);
- jbig2_arith_int_ctx_free(ctx, IAEX);
- jbig2_arith_int_ctx_free(ctx, IAAI);
- if (params->SDREFAGG) {
- jbig2_arith_iaid_ctx_free(ctx, IAID);
- jbig2_arith_int_ctx_free(ctx, IARDX);
- jbig2_arith_int_ctx_free(ctx, IARDY);
+cleanup4:
+ if (tparams != NULL)
+ {
+ if (!params->SDHUFF)
+ {
+ jbig2_arith_int_ctx_free(ctx, tparams->IADT);
+ jbig2_arith_int_ctx_free(ctx, tparams->IAFS);
+ jbig2_arith_int_ctx_free(ctx, tparams->IADS);
+ jbig2_arith_int_ctx_free(ctx, tparams->IAIT);
+ jbig2_arith_iaid_ctx_free(ctx, tparams->IAID);
+ jbig2_arith_int_ctx_free(ctx, tparams->IARI);
+ jbig2_arith_int_ctx_free(ctx, tparams->IARDW);
+ jbig2_arith_int_ctx_free(ctx, tparams->IARDH);
+ jbig2_arith_int_ctx_free(ctx, tparams->IARDX);
+ jbig2_arith_int_ctx_free(ctx, tparams->IARDY);
}
- jbig2_free(ctx->allocator, as);
- } else {
- if (params->SDREFAGG) {
- jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
+ else
+ {
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFFS);
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFDS);
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFDT);
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFRDX);
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFRDY);
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFRDW);
+ jbig2_release_huffman_table(ctx, tparams->SBHUFFRDH);
}
- jbig2_release_huffman_table(ctx, SDHUFFRDX);
- jbig2_free(ctx->allocator, hs);
+ jbig2_free(ctx->allocator, tparams);
}
+ if (refagg_dicts != NULL)
+ {
+ jbig2_sd_release(ctx, refagg_dicts[0]);
+ jbig2_free(ctx->allocator, refagg_dicts);
+ }
+ jbig2_free(ctx->allocator, GB_stats);
+cleanup2:
+ jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
+ jbig2_release_huffman_table(ctx, SDHUFFRDX);
+ jbig2_free(ctx->allocator, hs);
+ jbig2_arith_iaid_ctx_free(ctx, IAID);
+ jbig2_arith_int_ctx_free(ctx, IARDX);
+ jbig2_arith_int_ctx_free(ctx, IARDY);
+
+cleanup1:
jbig2_word_stream_buf_free(ctx, ws);
+ jbig2_free(ctx->allocator, as);
+ jbig2_arith_int_ctx_free(ctx, IADH);
+ jbig2_arith_int_ctx_free(ctx, IADW);
+ jbig2_arith_int_ctx_free(ctx, IAEX);
+ jbig2_arith_int_ctx_free(ctx, IAAI);
return SDEXSYMS;
}
@@ -759,6 +813,10 @@
/* 7.4.2.1.1 */
flags = jbig2_get_uint16(segment_data);
+
+ /* zero params to ease cleanup later */
+ memset(¶ms, 0, sizeof(Jbig2SymbolDictParams));
+
params.SDHUFF = flags & 1;
params.SDREFAGG = (flags >> 1) & 1;
params.SDTEMPLATE = (flags >> 10) & 3;
@@ -772,12 +830,10 @@
if (params.SDHUFF) {
switch ((flags & 0x000c) >> 2) {
case 0: /* Table B.4 */
- params.SDHUFFDH = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_D);
+ params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_D);
break;
case 1: /* Table B.5 */
- params.SDHUFFDH = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_E);
+ params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_E);
break;
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
@@ -788,8 +844,6 @@
params.SDHUFFDH = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
break;
- /* FIXME: this function leaks memory when error happens.
- i.e. not calling jbig2_release_huffman_table() */
case 2:
default:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -796,20 +850,26 @@
"symbol dictionary specified invalid huffman table");
break;
}
+ if (params.SDHUFFDH == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate DH huffman table");
+ goto cleanup;
+ }
+
switch ((flags & 0x0030) >> 4) {
case 0: /* Table B.2 */
- params.SDHUFFDW = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_B);
+ params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_B);
break;
case 1: /* Table B.3 */
- params.SDHUFFDW = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_C);
+ params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_C);
break;
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom DW huffman table not found (%d)", table_index);
+ break;
}
params.SDHUFFDW = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
@@ -820,34 +880,54 @@
"symbol dictionary specified invalid huffman table");
break;
}
+ if (params.SDHUFFDW == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate DW huffman table");
+ goto cleanup;
+ }
+
if (flags & 0x0040) {
/* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom BMSIZE huffman table not found (%d)", table_index);
+ } else {
+ params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, huffman_params);
+ ++table_index;
}
- params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, huffman_params);
- ++table_index;
} else {
/* Table B.1 */
- params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_A);
+ 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");
+ goto cleanup;
+ }
+
if (flags & 0x0080) {
/* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom REFAGG huffman table not found (%d)", table_index);
+ } else {
+ params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, huffman_params);
+ ++table_index;
}
- params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, huffman_params);
- ++table_index;
} else {
/* Table B.1 */
- params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx,
- &jbig2_huffman_params_A);
+ 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");
+ goto cleanup;
+ }
}
/* FIXME: there are quite a few of these conditions to check */
@@ -903,10 +983,22 @@
int n_dicts = jbig2_sd_count_referred(ctx, segment);
Jbig2SymbolDict **dicts = NULL;
- params.SDINSYMS = NULL;
if (n_dicts > 0) {
dicts = jbig2_sd_list_referred(ctx, segment);
+ if (dicts == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate dicts in symbol dictionary");
+ goto cleanup;
+ }
params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts);
+ if (params.SDINSYMS == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate symbol array in symbol dictionary");
+ jbig2_sd_release(ctx, *dicts);
+ goto cleanup;
+ }
}
if (params.SDINSYMS != NULL) {
params.SDNUMINSYMS = params.SDINSYMS->n_symbols;
@@ -918,13 +1010,26 @@
/* 7.4.2.2 (4) */
if (!params.SDHUFF) {
int stats_size = params.SDTEMPLATE == 0 ? 65536 :
- params.SDTEMPLATE == 1 ? 8192 : 1024;
+ params.SDTEMPLATE == 1 ? 8192 : 1024;
GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GB_stats == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate GB_stats in jbig2_symbol_dictionary");
+ goto cleanup;
+ }
memset(GB_stats, 0, stats_size);
if (params.SDREFAGG) {
- stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
- GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
- memset(GR_stats, 0, stats_size);
+ stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
+ GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GR_stats == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "failed to allocate GR_stats in jbig2_symbol_dictionary");
+ jbig2_free(ctx->allocator, GB_stats);
+ goto cleanup;
+ }
+ memset(GR_stats, 0, stats_size);
}
}
@@ -942,6 +1047,7 @@
if (segment->result) jbig2_dump_symbol_dict(ctx, segment);
#endif
+cleanup:
if (params.SDHUFF) {
jbig2_release_huffman_table(ctx, params.SDHUFFDH);
jbig2_release_huffman_table(ctx, params.SDHUFFDW);
--- a/jbig2_text.c
+++ b/jbig2_text.c
@@ -71,7 +71,7 @@
int x,y;
bool first_symbol;
uint32_t index, SBNUMSYMS;
- Jbig2Image *IB;
+ Jbig2Image *IB = NULL;
Jbig2HuffmanState *hs = NULL;
Jbig2HuffmanTable *SBSYMCODES = NULL;
int code = 0;
@@ -85,16 +85,22 @@
"symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts);
if (params->SBHUFF) {
- Jbig2HuffmanTable *runcodes;
+ Jbig2HuffmanTable *runcodes = NULL;
Jbig2HuffmanParams runcodeparams;
Jbig2HuffmanLine runcodelengths[35];
- Jbig2HuffmanLine *symcodelengths;
+ Jbig2HuffmanLine *symcodelengths = NULL;
Jbig2HuffmanParams symcodeparams;
- int code, err, len, range, r;
+ int err, len, range, r;
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"huffman coded text region");
hs = jbig2_huffman_new(ctx, ws);
+ if (hs == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "failed to allocate storage for text region");
+ return -1;
+ }
/* 7.4.3.1.7 - decode symbol ID Huffman table */
/* this is actually part of the segment header, but it is more
@@ -115,7 +121,8 @@
if (runcodes == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"error constructing symbol id runcode table!");
- return -1;
+ code = -1;
+ goto cleanup1;
}
/* decode the symbol id codelengths using the runlength table */
@@ -123,7 +130,8 @@
if (symcodelengths == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"memory allocation failure reading symbol ID huffman table!");
- return -1;
+ code = -1;
+ goto cleanup1;
}
index = 0;
while (index < SBNUMSYMS) {
@@ -131,7 +139,8 @@
if (err != 0 || code < 0 || code >= 35) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"error reading symbol ID huffman table!");
- return err ? err : -1;
+ code = err ? err : -1;
+ goto cleanup1;
}
if (code < 32) {
@@ -143,8 +152,8 @@
if (index < 1) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"error decoding symbol id table: run length with no antecedent!");
- /* todo: memory cleanup */
- return -1;
+ code = -1;
+ goto cleanup1;
}
} else {
len = 0; /* code == 33 or 34 */
@@ -183,13 +192,15 @@
/* finally, construct the symbol id huffman table itself */
SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams);
+cleanup1:
jbig2_free(ctx->allocator, symcodelengths);
jbig2_release_huffman_table(ctx, runcodes);
if (SBSYMCODES == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "could not construct Symbol ID huffman table!");
- return -1;
+ "could not construct Symbol ID huffman table!");
+ jbig2_huffman_free(ctx, hs);
+ return ((code != 0) ? code : -1);
}
}
@@ -201,6 +212,7 @@
STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
} else {
code = jbig2_arith_int_decode(params->IADT, as, &STRIPT);
+ if (code < 0) goto cleanup2;
}
/* 6.4.5 (2) */
@@ -215,6 +227,7 @@
DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
} else {
code = jbig2_arith_int_decode(params->IADT, as, &DT);
+ if (code < 0) goto cleanup2;
}
DT *= params->SBSTRIPS;
STRIPT += DT;
@@ -229,6 +242,7 @@
DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
} else {
code = jbig2_arith_int_decode(params->IAFS, as, &DFS);
+ if (code < 0) goto cleanup2;
}
FIRSTS += DFS;
CURS = FIRSTS;
@@ -254,6 +268,7 @@
CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS);
} else {
code = jbig2_arith_int_decode(params->IAIT, as, &CURT);
+ if (code < 0) goto cleanup2;
}
T = STRIPT + CURT;
@@ -262,6 +277,7 @@
ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
} else {
code = jbig2_arith_iaid_decode(params->IAID, as, (int *)&ID);
+ if (code < 0) goto cleanup2;
}
if (ID >= SBNUMSYMS) {
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -282,6 +298,7 @@
RI = jbig2_huffman_get_bits(hs, 1);
} else {
code = jbig2_arith_int_decode(params->IARI, as, &RI);
+ if (code < 0) goto cleanup2;
}
} else {
RI = 0;
@@ -295,10 +312,16 @@
/* 6.4.11 (1, 2, 3, 4) */
if (!params->SBHUFF) {
- code = jbig2_arith_int_decode(params->IARDW, as, &RDW);
- code = jbig2_arith_int_decode(params->IARDH, as, &RDH);
- code = jbig2_arith_int_decode(params->IARDX, as, &RDX);
- code = jbig2_arith_int_decode(params->IARDY, as, &RDY);
+ int code1 = jbig2_arith_int_decode(params->IARDW, as, &RDW);
+ int code2 = jbig2_arith_int_decode(params->IARDH, as, &RDH);
+ int code3 = jbig2_arith_int_decode(params->IARDX, as, &RDX);
+ int code4 = jbig2_arith_int_decode(params->IARDY, as, &RDY);
+ if ((code1 < 0) || (code2 < 0) || (code3 < 0) || (code4 < 0))
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to decode data");
+ goto cleanup2;
+ }
} else {
RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code);
RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code);
@@ -394,11 +417,12 @@
}
/* 6.4.5 (4) */
+cleanup2:
if (params->SBHUFF) {
jbig2_release_huffman_table(ctx, SBSYMCODES);
}
- return 0;
+ return code;
}
/**
@@ -410,10 +434,10 @@
int offset = 0;
Jbig2RegionSegmentInfo region_info;
Jbig2TextRegionParams params;
- Jbig2Image *image;
- Jbig2SymbolDict **dicts;
- int n_dicts;
- uint16_t flags;
+ Jbig2Image *image = NULL;
+ Jbig2SymbolDict **dicts = NULL;
+ int n_dicts = 0;
+ uint16_t flags = 0;
uint16_t huffman_flags = 0;
Jbig2ArithCx *GR_stats = NULL;
int code = 0;
@@ -420,7 +444,7 @@
Jbig2WordStream *ws = NULL;
Jbig2ArithState *as = NULL;
int table_index = 0;
- const Jbig2HuffmanParams *huffman_params;
+ const Jbig2HuffmanParams *huffman_params = NULL;
/* 7.4.1 */
if (segment->data_length < 17)
@@ -435,6 +459,9 @@
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"text region header flags 0x%04x", flags);
+ /* zero params to ease cleanup later */
+ memset(¶ms, 0, sizeof(Jbig2TextRegionParams));
+
params.SBHUFF = flags & 0x0001;
params.SBREFINE = flags & 0x0002;
params.LOGSBSTRIPS = (flags & 0x000c) >> 2;
@@ -473,9 +500,6 @@
params.sbrat[2] = segment_data[offset + 2];
params.sbrat[3] = segment_data[offset + 3];
offset += 4;
- } else {
- /* zero these for the sake of later debug messages */
- memset(params.sbrat, 0, sizeof(params.sbrat));
}
}
@@ -485,7 +509,7 @@
if (params.SBHUFF) {
/* 7.4.3.1.5 - Symbol ID Huffman table */
- /* ...this is handled in the segment body decoder */
+ /* ...this is handled in the segment body decoder */
/* 7.4.3.1.6 - Other Huffman table selection */
switch (huffman_flags & 0x0003) {
@@ -500,20 +524,27 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom FS huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFFS = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
- /* FIXME: this function leaks memory when error happens.
- i.e. not calling jbig2_release_huffman_table() */
break;
case 2: /* invalid */
default:
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "text region specified invalid FS huffman table");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "text region specified invalid FS huffman table");
+ goto cleanup1;
break;
}
+ if (params.SBHUFFFS == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified FS huffman table");
+ goto cleanup1;
+ }
+
switch ((huffman_flags & 0x000c) >> 2) {
case 0: /* Table B.8 */
params.SBHUFFDS = jbig2_build_huffman_table(ctx,
@@ -530,13 +561,21 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom DS huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFDS = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
break;
}
+ if (params.SBHUFFDS == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified DS huffman table");
+ goto cleanup1;
+ }
+
switch ((huffman_flags & 0x0030) >> 4) {
case 0: /* Table B.11 */
params.SBHUFFDT = jbig2_build_huffman_table(ctx,
@@ -553,13 +592,21 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom DT huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFDT = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
break;
}
+ if (params.SBHUFFDT == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified DT huffman table");
+ goto cleanup1;
+ }
+
switch ((huffman_flags & 0x00c0) >> 6) {
case 0: /* Table B.14 */
params.SBHUFFRDW = jbig2_build_huffman_table(ctx,
@@ -572,8 +619,9 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom RDW huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFRDW = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
@@ -580,10 +628,18 @@
break;
case 2: /* invalid */
default:
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "text region specified invalid RDW huffman table");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "text region specified invalid RDW huffman table");
+ goto cleanup1;
break;
}
+ if (params.SBHUFFRDW == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified RDW huffman table");
+ goto cleanup1;
+ }
+
switch ((huffman_flags & 0x0300) >> 8) {
case 0: /* Table B.14 */
params.SBHUFFRDH = jbig2_build_huffman_table(ctx,
@@ -596,8 +652,9 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom RDH huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFRDH = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
@@ -604,11 +661,19 @@
break;
case 2: /* invalid */
default:
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "text region specified invalid RDH huffman table");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "text region specified invalid RDH huffman table");
+ goto cleanup1;
break;
}
- switch ((huffman_flags & 0x0c00) >> 10) {
+ if (params.SBHUFFRDH == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified RDH huffman table");
+ goto cleanup1;
+ }
+
+ switch ((huffman_flags & 0x0c00) >> 10) {
case 0: /* Table B.14 */
params.SBHUFFRDX = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_N);
@@ -620,8 +685,9 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom RDX huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFRDX = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
@@ -628,10 +694,18 @@
break;
case 2: /* invalid */
default:
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "text region specified invalid RDX huffman table");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "text region specified invalid RDX huffman table");
+ goto cleanup1;
break;
}
+ if (params.SBHUFFRDX == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified RDX huffman table");
+ goto cleanup1;
+ }
+
switch ((huffman_flags & 0x3000) >> 12) {
case 0: /* Table B.14 */
params.SBHUFFRDY = jbig2_build_huffman_table(ctx,
@@ -644,8 +718,9 @@
case 3: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom RDY huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFRDY = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
@@ -652,10 +727,18 @@
break;
case 2: /* invalid */
default:
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "text region specified invalid RDY huffman table");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "text region specified invalid RDY huffman table");
+ goto cleanup1;
break;
}
+ if (params.SBHUFFRDY == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified RDY huffman table");
+ goto cleanup1;
+ }
+
switch ((huffman_flags & 0x4000) >> 14) {
case 0: /* Table B.1 */
params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx,
@@ -664,13 +747,20 @@
case 1: /* Custom table from referred segment */
huffman_params = jbig2_find_table(ctx, segment, table_index);
if (huffman_params == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Custom RSIZE huffman table not found (%d)", table_index);
+ goto cleanup1;
}
params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
break;
}
+ if (params.SBHUFFRSIZE == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to allocate text region specified RSIZE huffman table");
+ goto cleanup1;
+ }
if (huffman_flags & 0x8000) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
@@ -691,19 +781,20 @@
if (n_dicts != 0) {
dicts = jbig2_sd_list_referred(ctx, segment);
} else {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "text region refers to no symbol dictionaries!");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "text region refers to no symbol dictionaries!");
+ goto cleanup1;
}
if (dicts == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "unable to retrive symbol dictionaries!"
- " previous parsing error?");
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "unable to retrive symbol dictionaries! previous parsing error?");
+ goto cleanup1;
} else {
int index;
if (dicts[0] == NULL) {
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING,
- segment->number,
- "unable to find first referenced symbol dictionary!");
+ code =jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "unable to find first referenced symbol dictionary!");
+ goto cleanup1;
}
for (index = 1; index < n_dicts; index++)
if (dicts[index] == NULL) {
@@ -717,28 +808,30 @@
if (!params.SBHUFF && params.SBREFINE) {
int stats_size = params.SBRTEMPLATE ? 1 << 10 : 1 << 13;
GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
+ if (GR_stats == NULL)
+ {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "could not allocate GR_stats");
+ goto cleanup1;
+ }
memset(GR_stats, 0, stats_size);
}
image = jbig2_image_new(ctx, region_info.width, region_info.height);
if (image == NULL) {
- if (!params.SBHUFF && params.SBREFINE) {
- jbig2_free(ctx->allocator, GR_stats);
- } else if (params.SBHUFF) {
- jbig2_release_huffman_table(ctx, params.SBHUFFFS);
- jbig2_release_huffman_table(ctx, params.SBHUFFDS);
- jbig2_release_huffman_table(ctx, params.SBHUFFDT);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
- jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
- }
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "couldn't allocate text region image");
+ code =jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "couldn't allocate text region image");
+ goto cleanup1;
}
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 text region image");
+ jbig2_image_release(ctx, image);
+ goto cleanup2;
+ }
if (!params.SBHUFF) {
int SBSYMCODELEN, index;
int SBNUMSYMS = 0;
@@ -747,60 +840,48 @@
}
as = jbig2_arith_new(ctx, ws);
+ params.IADT = jbig2_arith_int_ctx_new(ctx);
+ params.IAFS = jbig2_arith_int_ctx_new(ctx);
+ params.IADS = jbig2_arith_int_ctx_new(ctx);
+ params.IAIT = jbig2_arith_int_ctx_new(ctx);
+ if ((as == NULL) || (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");
+ goto cleanup3;
+ }
- params.IADT = jbig2_arith_int_ctx_new(ctx);
- params.IAFS = jbig2_arith_int_ctx_new(ctx);
- params.IADS = jbig2_arith_int_ctx_new(ctx);
- params.IAIT = jbig2_arith_int_ctx_new(ctx);
/* Table 31 */
for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < SBNUMSYMS; SBSYMCODELEN++);
- params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
+ params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
params.IARI = jbig2_arith_int_ctx_new(ctx);
params.IARDW = jbig2_arith_int_ctx_new(ctx);
params.IARDH = jbig2_arith_int_ctx_new(ctx);
params.IARDX = jbig2_arith_int_ctx_new(ctx);
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");
+ goto cleanup4;
}
+ }
code = jbig2_decode_text_region(ctx, segment, ¶ms,
- (const Jbig2SymbolDict * const *)dicts, n_dicts, image,
- segment_data + offset, segment->data_length - offset,
+ (const Jbig2SymbolDict * const *)dicts, n_dicts, image,
+ segment_data + offset, segment->data_length - offset,
GR_stats, as, as ? NULL : ws);
-
- if (!params.SBHUFF && params.SBREFINE) {
- jbig2_free(ctx->allocator, GR_stats);
+ if (code < 0)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "failed to decode text region image data");
+ jbig2_image_release(ctx, image);
+ goto cleanup4;
}
- if (params.SBHUFF) {
- jbig2_release_huffman_table(ctx, params.SBHUFFFS);
- jbig2_release_huffman_table(ctx, params.SBHUFFDS);
- jbig2_release_huffman_table(ctx, params.SBHUFFDT);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
- jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
- jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
- jbig2_word_stream_buf_free(ctx, ws);
- }
- else {
- jbig2_arith_int_ctx_free(ctx, params.IADT);
- jbig2_arith_int_ctx_free(ctx, params.IAFS);
- jbig2_arith_int_ctx_free(ctx, params.IADS);
- jbig2_arith_int_ctx_free(ctx, params.IAIT);
- jbig2_arith_iaid_ctx_free(ctx, params.IAID);
- jbig2_arith_int_ctx_free(ctx, params.IARI);
- jbig2_arith_int_ctx_free(ctx, params.IARDW);
- jbig2_arith_int_ctx_free(ctx, params.IARDH);
- jbig2_arith_int_ctx_free(ctx, params.IARDX);
- jbig2_arith_int_ctx_free(ctx, params.IARDY);
- jbig2_free(ctx->allocator, as);
- jbig2_word_stream_buf_free(ctx, ws);
- }
-
- jbig2_free(ctx->allocator, dicts);
-
- /* todo: check errors */
-
if ((segment->flags & 63) == 4) {
/* we have an intermediate region here. save it for later */
segment->result = image;
@@ -809,15 +890,51 @@
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);
+ jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image,
+ region_info.x, region_info.y, region_info.op);
jbig2_image_release(ctx, image);
}
- /* success */
- return 0;
+cleanup4:
+ if (!params.SBHUFF) {
+ jbig2_arith_iaid_ctx_free(ctx, params.IAID);
+ jbig2_arith_int_ctx_free(ctx, params.IARI);
+ jbig2_arith_int_ctx_free(ctx, params.IARDW);
+ jbig2_arith_int_ctx_free(ctx, params.IARDH);
+ jbig2_arith_int_ctx_free(ctx, params.IARDX);
+ jbig2_arith_int_ctx_free(ctx, params.IARDY);
+ }
- too_short:
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "Segment too short");
+cleanup3:
+ if (!params.SBHUFF) {
+ jbig2_arith_int_ctx_free(ctx, params.IADT);
+ jbig2_arith_int_ctx_free(ctx, params.IAFS);
+ jbig2_arith_int_ctx_free(ctx, params.IADS);
+ jbig2_arith_int_ctx_free(ctx, params.IAIT);
+ jbig2_free(ctx->allocator, as);
+ }
+ jbig2_word_stream_buf_free(ctx, ws);
+
+cleanup2:
+ if (!params.SBHUFF && params.SBREFINE) {
+ jbig2_free(ctx->allocator, GR_stats);
+ }
+
+cleanup1:
+ if (params.SBHUFF) {
+ jbig2_release_huffman_table(ctx, params.SBHUFFFS);
+ jbig2_release_huffman_table(ctx, params.SBHUFFDS);
+ jbig2_release_huffman_table(ctx, params.SBHUFFDT);
+ jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
+ jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
+ jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
+ jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
+ jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
+ }
+
+ return code;
+
+too_short:
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+ "Segment too short");
}