ref: 471dabc8b157f9a841e4f0090e3c2ff016915fd9
parent: 398186762d6f73d1632d8c6d846f2066c3087751
author: Sebastian Rasmussen <sebras@gmail.com>
date: Thu Apr 5 20:41:01 EDT 2018
jbig2dec: Improve error handling. Some functions detected errors but would not return these to the caller. These functions may now indicate errors: jbig2_arith_decode(), jbig2_image_resize() Errors detected by following functions were not always handled, but they are now handled properly: jbig2_arith_decode(), jbig2_arith_iaid_decode() jbig2_arith_int_ctx_new(), jbig2_build_huffman_table() jbig2_complete_page(), jbig2_image_compose() jbig2_decode_refinement_region(), jbig2_ctx_new() jbig2_image_resize(), jbig2_image_write_pbm() jbig2_image_write_pbm_file(), jbig2_image_write_png() jbig2_image_write_png_file(), jbig2_metadata_add() jbig2_page_add_result(), jbig2_renew() jbig2_strndup() Some functions detected errors but did not fail early enough: jbig2_decode_pattern_dict(), jbig2_decode_halftone_region() jbig2_decode_mmr_line() detected errors but did not produce suitable error messages. This has been rectified. Finally, if a subfunction indicates an error by returning an error code, the calling function will report a warning and return, indicating failure.
--- a/jbig2.c
+++ b/jbig2.c
@@ -294,7 +294,17 @@
ctx->buf_rd_ix += header_size;
if (ctx->n_segments == ctx->n_segments_max)
- ctx->segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
+ {
+ Jbig2Segment **segments;
+ segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
+ if (segments == NULL)
+ {
+ ctx->state = JBIG2_FILE_EOF;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "could not reallocate space for more segments");
+ }
+ ctx->segments = segments;
+ }
+
ctx->segments[ctx->n_segments++] = segment;
if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) {
--- a/jbig2_arith.c
+++ b/jbig2_arith.c
@@ -263,7 +263,7 @@
}
bool
-jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx)
+jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx, int *code)
{
Jbig2ArithCx cx = *pcx;
const Jbig2ArithQe *pqe;
@@ -271,7 +271,8 @@
bool D;
if (index >= MAX_QE_ARRAY_SIZE) {
- return -1;
+ *code = -1;
+ return 0;
} else {
pqe = &jbig2_arith_Qe[index];
}
@@ -354,6 +355,7 @@
Jbig2ArithState *as;
int i;
Jbig2ArithCx cx = 0;
+ int code;
ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL);
@@ -369,7 +371,7 @@
#else
(void)
#endif
- jbig2_arith_decode(as, &cx);
+ jbig2_arith_decode(as, &cx, &code);
#ifdef JBIG2_DEBUG_ARITH
fprintf(stderr, "%3d: D = %d, ", i, D);
--- a/jbig2_arith.h
+++ b/jbig2_arith.h
@@ -28,7 +28,7 @@
Jbig2ArithState *jbig2_arith_new(Jbig2Ctx *ctx, Jbig2WordStream *ws);
/* decode a bit */
-bool jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx);
+bool jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx, int *code);
/* returns true if the end of the data stream has been reached (for sanity checks) */
bool jbig2_arith_has_reached_marker(Jbig2ArithState *as);
--- a/jbig2_arith_iaid.c
+++ b/jbig2_arith_iaid.c
@@ -66,17 +66,20 @@
/* A.3 */
/* Return value: -1 on error, 0 on normal value */
int
-jbig2_arith_iaid_decode(Jbig2ArithIaidCtx *ctx, Jbig2ArithState *as, int32_t *p_result)
+jbig2_arith_iaid_decode(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *actx, Jbig2ArithState *as, int32_t *p_result)
{
- Jbig2ArithCx *IAIDx = ctx->IAIDx;
- int SBSYMCODELEN = ctx->SBSYMCODELEN;
+ Jbig2ArithCx *IAIDx = actx->IAIDx;
+ int SBSYMCODELEN = actx->SBSYMCODELEN;
int PREV = 1;
int D;
int i;
+ int code = 0;
/* A.3 (2) */
for (i = 0; i < SBSYMCODELEN; i++) {
- D = jbig2_arith_decode(as, &IAIDx[PREV]);
+ D = jbig2_arith_decode(as, &IAIDx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAIDx code");
#ifdef VERBOSE
fprintf(stderr, "IAID%x: D = %d\n", PREV, D);
#endif
--- a/jbig2_arith_iaid.h
+++ b/jbig2_arith_iaid.h
@@ -21,6 +21,6 @@
Jbig2ArithIaidCtx *jbig2_arith_iaid_ctx_new(Jbig2Ctx *ctx, int SBSYMCODELEN);
-int jbig2_arith_iaid_decode(Jbig2ArithIaidCtx *ctx, Jbig2ArithState *as, int32_t *p_result);
+int jbig2_arith_iaid_decode(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *actx, Jbig2ArithState *as, int32_t *p_result);
void jbig2_arith_iaid_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIaidCtx *iax);
--- a/jbig2_arith_int.c
+++ b/jbig2_arith_int.c
@@ -53,34 +53,47 @@
/* A.2 */
/* Return value: -1 on error, 0 on normal value, 1 on OOB return. */
int
-jbig2_arith_int_decode(Jbig2ArithIntCtx *ctx, Jbig2ArithState *as, int32_t *p_result)
+jbig2_arith_int_decode(Jbig2Ctx *ctx, Jbig2ArithIntCtx *actx, Jbig2ArithState *as, int32_t *p_result)
{
- Jbig2ArithCx *IAx = ctx->IAx;
+ Jbig2ArithCx *IAx = actx->IAx;
int PREV = 1;
int S, V;
int bit;
int n_tail, offset;
int i;
+ int code = 0;
- S = jbig2_arith_decode(as, &IAx[PREV]);
+ S = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx S");
PREV = (PREV << 1) | S;
- bit = jbig2_arith_decode(as, &IAx[PREV]);
+ bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 0");
PREV = (PREV << 1) | bit;
if (bit) {
- bit = jbig2_arith_decode(as, &IAx[PREV]);
+ bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 1");
PREV = (PREV << 1) | bit;
if (bit) {
- bit = jbig2_arith_decode(as, &IAx[PREV]);
+ bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 2");
PREV = (PREV << 1) | bit;
if (bit) {
- bit = jbig2_arith_decode(as, &IAx[PREV]);
+ bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 3");
PREV = (PREV << 1) | bit;
if (bit) {
- bit = jbig2_arith_decode(as, &IAx[PREV]);
+ bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx bit 4");
PREV = (PREV << 1) | bit;
if (bit) {
@@ -109,7 +122,9 @@
V = 0;
for (i = 0; i < n_tail; i++) {
- bit = jbig2_arith_decode(as, &IAx[PREV]);
+ bit = jbig2_arith_decode(as, &IAx[PREV], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx code 7");
PREV = ((PREV << 1) & 511) | (PREV & 256) | bit;
V = (V << 1) | bit;
}
--- a/jbig2_arith_int.h
+++ b/jbig2_arith_int.h
@@ -21,6 +21,6 @@
Jbig2ArithIntCtx *jbig2_arith_int_ctx_new(Jbig2Ctx *ctx);
-int jbig2_arith_int_decode(Jbig2ArithIntCtx *ctx, Jbig2ArithState *as, int32_t *p_result);
+int jbig2_arith_int_decode(Jbig2Ctx *ctx, Jbig2ArithIntCtx *actx, Jbig2ArithState *as, int32_t *p_result);
void jbig2_arith_int_ctx_free(Jbig2Ctx *ctx, Jbig2ArithIntCtx *iax);
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -76,6 +76,7 @@
uint32_t line_m1;
uint32_t line_m2;
int padded_width = (GBW + 7) & -8;
+ int code = 0;
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0;
@@ -97,7 +98,9 @@
for (x_minor = 0; x_minor < minor_width; x_minor++) {
bool bit;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0");
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit | ((line_m1 >> (7 - x_minor)) & 0x10) | ((line_m2 >> (7 - x_minor)) & 0x800);
}
@@ -125,6 +128,7 @@
uint32_t CONTEXT;
int x, y;
bool bit;
+ int code = 0;
if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
pixel_outside_field(params->gbat[2], params->gbat[3]) ||
@@ -154,7 +158,9 @@
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0");
jbig2_image_set_pixel(image, x, y, bit);
}
}
@@ -171,6 +177,7 @@
const int rowstride = image->stride;
int x, y;
byte *gbreg_line = (byte *) image->data;
+ int code = 0;
/* todo: currently we only handle the nominal gbat location */
/* when resolved make sure to call jbig2_check_adaptive_pixel_in_field() */
@@ -208,7 +215,9 @@
for (x_minor = 0; x_minor < minor_width; x_minor++) {
bool bit;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template1");
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0xefb) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x8) | ((line_m2 >> (8 - x_minor)) & 0x200);
}
@@ -233,6 +242,7 @@
const int rowstride = image->stride;
int x, y;
byte *gbreg_line = (byte *) image->data;
+ int code = 0;
/* todo: currently we only handle the nominal gbat location */
/* when resolved make sure to call jbig2_check_adaptive_pixel_in_field() */
@@ -270,7 +280,9 @@
for (x_minor = 0; x_minor < minor_width; x_minor++) {
bool bit;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2");
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
}
@@ -295,6 +307,7 @@
const int rowstride = image->stride;
int x, y;
byte *gbreg_line = (byte *) image->data;
+ int code = 0;
/* This is a special case for GBATX1 = 3, GBATY1 = -1 */
@@ -331,7 +344,9 @@
for (x_minor = 0; x_minor < minor_width; x_minor++) {
bool bit;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2a");
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
((line_m1 >> (10 - x_minor)) & 0x8) | ((line_m1 >> (9 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
@@ -389,7 +404,9 @@
for (x_minor = 0; x_minor < minor_width; x_minor++) {
bool bit;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3");
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x010);
}
@@ -415,6 +432,7 @@
uint32_t CONTEXT;
int x, y;
bool bit;
+ int code = 0;
if (pixel_outside_field(params->gbat[0], params->gbat[1]))
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -435,7 +453,9 @@
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3");
jbig2_image_set_pixel(image, x, y, bit);
}
}
@@ -467,6 +487,7 @@
int x, y;
bool bit;
int LTP = 0;
+ int code = 0;
if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
pixel_outside_field(params->gbat[2], params->gbat[3]) ||
@@ -476,7 +497,9 @@
"adaptive template pixel is out of field");
for (y = 0; y < GBH; y++) {
- LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25]);
+ LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -495,7 +518,9 @@
CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 13;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0 TPGDON2");
jbig2_image_set_pixel(image, x, y, bit);
}
} else {
@@ -517,6 +542,7 @@
int x, y;
bool bit;
int LTP = 0;
+ int code = 0;
if (pixel_outside_field(params->gbat[0], params->gbat[1]))
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -523,7 +549,9 @@
"adaptive template pixel is out of field");
for (y = 0; y < GBH; y++) {
- LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795]);
+ LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template1 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -539,7 +567,9 @@
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 11;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template1 TPGDON2");
jbig2_image_set_pixel(image, x, y, bit);
}
} else {
@@ -561,6 +591,7 @@
int x, y;
bool bit;
int LTP = 0;
+ int code = 0;
if (pixel_outside_field(params->gbat[0], params->gbat[1]))
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -567,7 +598,9 @@
"adaptive template pixel is out of field");
for (y = 0; y < GBH; y++) {
- LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5]);
+ LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -580,7 +613,9 @@
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 8;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2 TPGDON2");
jbig2_image_set_pixel(image, x, y, bit);
}
} else {
@@ -602,6 +637,7 @@
int x, y;
bool bit;
int LTP = 0;
+ int code = 0;
if (pixel_outside_field(params->gbat[0], params->gbat[1]))
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -608,7 +644,9 @@
"adaptive template pixel is out of field");
for (y = 0; y < GBH; y++) {
- LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195]);
+ LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
@@ -621,7 +659,9 @@
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template3 TPGDON2");
jbig2_image_set_pixel(image, x, y, bit);
}
} else {
@@ -791,8 +831,9 @@
}
if (code >= 0)
- jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
- else
+ 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");
cleanup:
--- a/jbig2_halftone.c
+++ b/jbig2_halftone.c
@@ -44,7 +44,9 @@
const int N = params->GRAYMAX + 1;
const int HPW = params->HDPW;
const int HPH = params->HDPH;
+ int code;
int i;
+ int j;
/* allocate a new struct */
new = jbig2_new(ctx, Jbig2PatternDict, 1);
@@ -63,7 +65,6 @@
for (i = 0; i < N; i++) {
new->patterns[i] = jbig2_image_new(ctx, HPW, HPH);
if (new->patterns[i] == NULL) {
- int j;
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to allocate pattern element image");
for (j = 0; j < i; j++)
@@ -74,7 +75,14 @@
/* compose with the REPLACE operator; the source
will be clipped to the destination, selecting the
proper sub image */
- jbig2_image_compose(ctx, new->patterns[i], image, -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
+ code = jbig2_image_compose(ctx, new->patterns[i], image, -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to compose image into collective bitmap dictionary");
+ for (j = 0; j < i; j++)
+ jbig2_free(ctx->allocator, new->patterns[j]);
+ jbig2_free(ctx->allocator, new);
+ return NULL;
+ }
}
} else {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate collective bitmap dictionary");
@@ -169,6 +177,8 @@
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_image_release(ctx, image);
return hd;
@@ -452,6 +462,7 @@
uint32_t mg, ng;
int32_t x, y;
uint8_t gray_val;
+ int code;
/* 6.6.5 point 1. Fill bitmap with HDEFPIXEL */
memset(image->data, params->HDEFPIXEL, image->stride * image->height);
@@ -498,7 +509,11 @@
/* use highest available pattern */
gray_val = HNUMPATS - 1;
}
- jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
+ code = jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose pattern with gray-scale image");
+ return -1;
+ }
}
}
@@ -592,6 +607,10 @@
}
code = jbig2_decode_halftone_region(ctx, segment, ¶ms, segment_data + offset, segment->data_length - offset, image, GB_stats);
+ if (code < 0) {
+ jbig2_image_release(ctx, image);
+ return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to decode halftone region");
+ }
/* todo: retain GB_stats? */
if (!params.HMMR) {
@@ -598,7 +617,13 @@
jbig2_free(ctx->allocator, GB_stats);
}
- jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+ code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+ if (code < 0)
+ {
+ jbig2_image_release(ctx, image);
+ return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable add halftone region to page");
+ }
+
jbig2_image_release(ctx, image);
return code;
--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -132,7 +132,7 @@
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "jbig2_image_resize called with a different width (NYI)");
}
- return NULL;
+ return image;
}
/* composite one jbig2_image onto another
--- a/jbig2_image_pbm.c
+++ b/jbig2_image_pbm.c
@@ -35,7 +35,7 @@
jbig2_image_write_pbm_file(Jbig2Image *image, char *filename)
{
FILE *out;
- int error;
+ int code;
if ((out = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "unable to open '%s' for writing", filename);
@@ -42,10 +42,10 @@
return 1;
}
- error = jbig2_image_write_pbm(image, out);
+ code = jbig2_image_write_pbm(image, out);
fclose(out);
- return (error);
+ return (code);
}
/* write out an image struct as a pbm stream to an open file pointer */
--- a/jbig2_image_png.c
+++ b/jbig2_image_png.c
@@ -138,7 +138,7 @@
jbig2_image_write_png_file(Jbig2Image *image, char *filename)
{
FILE *out;
- int error;
+ int code;
if ((out = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "unable to open '%s' for writing\n", filename);
@@ -145,8 +145,8 @@
return 1;
}
- error = jbig2_image_write_png(image, out);
+ code = jbig2_image_write_png(image, out);
fclose(out);
- return (error);
+ return (code);
}
--- a/jbig2_metadata.c
+++ b/jbig2_metadata.c
@@ -107,6 +107,11 @@
/* copy the passed key,value pair */
md->keys[md->entries] = jbig2_strndup(ctx, key, key_length);
md->values[md->entries] = jbig2_strndup(ctx, value, value_length);
+ if (md->keys[md->entries] == NULL || md->values[md->entries] == NULL)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to accomodate more metadata");
+ return -1;
+ }
md->entries++;
return 0;
@@ -120,6 +125,7 @@
char *end = (char *)(segment_data + segment->data_length);
Jbig2Metadata *comment;
char *key, *value;
+ int code;
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "ASCII comment data");
@@ -139,7 +145,11 @@
if (!s)
goto too_short;
s++;
- jbig2_metadata_add(ctx, comment, key, value - key, value, s - value);
+ code = jbig2_metadata_add(ctx, comment, key, value - key, value, s - value);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add ascii comment data");
+ return -1;
+ }
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "'%s'\t'%s'", key, value);
}
--- a/jbig2_mmr.c
+++ b/jbig2_mmr.c
@@ -831,7 +831,7 @@
}
static int
-jbig2_decode_mmr_line(Jbig2MmrCtx *mmr, const byte *ref, byte *dst)
+jbig2_decode_mmr_line(Jbig2Ctx *ctx, Jbig2MmrCtx *mmr, const byte *ref, byte *dst)
{
uint32_t a0 = MINUS1;
uint32_t a1, a2, b1, b2;
@@ -863,7 +863,7 @@
if (a2 > mmr->width)
a2 = mmr->width;
if (a1 == MINUS1 || a2 < a1)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative black run");
jbig2_set_bits(dst, a1, a2);
a0 = a2;
/* printf ("H %d %d\n", white_run, black_run); */
@@ -877,7 +877,7 @@
if (a2 > mmr->width)
a2 = mmr->width;
if (a0 == MINUS1 || a1 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, a1);
a0 = a2;
/* printf ("H %d %d\n", black_run, white_run); */
@@ -891,7 +891,7 @@
b2 = jbig2_find_changing_element(ref, b1, mmr->width);
if (c) {
if (a0 == MINUS1 || b2 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b2);
}
a0 = b2;
@@ -903,7 +903,7 @@
b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
if (c) {
if (a0 == MINUS1 || b1 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1);
}
a0 = b1;
@@ -918,7 +918,7 @@
break;
if (c) {
if (a0 == MINUS1 || b1 + 1 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1 + 1);
}
a0 = b1 + 1;
@@ -933,7 +933,7 @@
break;
if (c) {
if (a0 == MINUS1 || b1 + 2 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1 + 2);
}
a0 = b1 + 2;
@@ -948,7 +948,7 @@
break;
if (c) {
if (a0 == MINUS1 || b1 + 3 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1 + 3);
}
a0 = b1 + 3;
@@ -963,7 +963,7 @@
break;
if (c) {
if (a0 == MINUS1 || b1 - 1 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1 - 1);
}
a0 = b1 - 1;
@@ -978,7 +978,7 @@
break;
if (c) {
if (a0 == MINUS1 || b1 - 2 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1 - 2);
}
a0 = b1 - 2;
@@ -993,7 +993,7 @@
break;
if (c) {
if (a0 == MINUS1 || b1 - 3 < a0)
- return -1;
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "negative white run");
jbig2_set_bits(dst, a0, b1 - 3);
}
a0 = b1 - 3;
@@ -1021,9 +1021,12 @@
for (y = 0; y < image->height; y++) {
memset(dst, 0, rowstride);
- code = jbig2_decode_mmr_line(&mmr, ref, dst);
+ code = jbig2_decode_mmr_line(ctx, &mmr, ref, dst);
if (code < 0)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode mmr line");
return code;
+ }
ref = dst;
dst += rowstride;
}
@@ -1060,9 +1063,12 @@
for (y = 0; y < image->height; y++) {
memset(dst, 0, rowstride);
- code = jbig2_decode_mmr_line(&mmr, ref, dst);
+ code = jbig2_decode_mmr_line(ctx, &mmr, ref, dst);
if (code < 0)
+ {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to decode halftone mmr line");
return code;
+ }
ref = dst;
dst += rowstride;
}
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -59,7 +59,7 @@
int
jbig2_page_info(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
{
- Jbig2Page *page;
+ Jbig2Page *page, *pages;
/* a new page info segment implies the previous page is finished */
page = &(ctx->pages[ctx->current_page]);
@@ -77,7 +77,11 @@
index++;
if (index >= ctx->max_page_index) {
/* grow the list */
- ctx->pages = jbig2_renew(ctx, ctx->pages, Jbig2Page, (ctx->max_page_index <<= 2));
+ pages = jbig2_renew(ctx, ctx->pages, Jbig2Page, (ctx->max_page_index <<= 2));
+ if (pages == NULL) {
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to reallocate space for more pages");
+ }
+ ctx->pages = pages;
for (j = index; j < ctx->max_page_index; j++) {
ctx->pages[j].state = JBIG2_PAGE_FREE;
ctx->pages[j].number = 0;
@@ -200,7 +204,7 @@
}
/* ensure image exists before marking page as complete */
- if (ctx->pages[ctx->current_page].image != NULL) {
+ if (!code && ctx->pages[ctx->current_page].image != NULL) {
ctx->pages[ctx->current_page].state = JBIG2_PAGE_COMPLETE;
}
@@ -214,6 +218,7 @@
jbig2_end_of_page(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
{
uint32_t page_number = ctx->pages[ctx->current_page].number;
+ int code;
if (segment->page_association != page_number) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
@@ -222,10 +227,17 @@
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of page %d", page_number);
- jbig2_complete_page(ctx);
+ code = jbig2_complete_page(ctx);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to complete page");
+ return -1;
+ }
#ifdef OUTPUT_PBM
- jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
+ code = jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "failed to write page image");
+ }
#endif
return 0;
@@ -240,6 +252,8 @@
int
jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *image, int x, int y, Jbig2ComposeOp op)
{
+ int code;
+
/* ensure image exists first */
if (page->image == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "page info possibly missing, no image defined");
@@ -251,12 +265,21 @@
uint32_t new_height = y + image->height + page->end_row;
if (page->image->height < new_height) {
+ Jbig2Image *resized_image = NULL;
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "growing page buffer to %d rows " "to accomodate new stripe", new_height);
- jbig2_image_resize(ctx, page->image, page->image->width, new_height);
+ resized_image = jbig2_image_resize(ctx, page->image, page->image->width, new_height);
+ if (resized_image == NULL) {
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "unable to resize image to accomodate new stripe");
+ }
+ page->image = resized_image;
}
}
- jbig2_image_compose(ctx, page->image, image, x, y + page->end_row, op);
+ code = jbig2_image_compose(ctx, page->image, image, x, y + page->end_row, op);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to compose image with page");
+ return -1;
+ }
return 0;
}
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -60,6 +60,7 @@
uint32_t CONTEXT;
int x, y;
bool bit;
+ int code = 0;
for (y = 0; y < GRH; y++) {
for (x = 0; x < GRW; x++) {
@@ -77,7 +78,9 @@
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
- bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement template0");
jbig2_image_set_pixel(image, x, y, bit);
}
}
@@ -85,11 +88,16 @@
{
static count = 0;
char name[32];
+ int code;
snprintf(name, 32, "refin-%d.pbm", count);
- jbig2_image_write_pbm_file(ref, name);
+ code = jbig2_image_write_pbm_file(ref, name);
+ if (code < 0)
+ return jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed write refinement input");
snprintf(name, 32, "refout-%d.pbm", count);
- jbig2_image_write_pbm_file(image, name);
+ code = jbig2_image_write_pbm_file(image, name);
+ if (code < 0)
+ return jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed write refinement output");
count++;
}
#endif
@@ -110,6 +118,7 @@
uint32_t CONTEXT;
int x, y;
bool bit;
+ int code = 0;
for (y = 0; y < GRH; y++) {
for (x = 0; x < GRW; x++) {
@@ -124,7 +133,9 @@
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
- bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement template0");
jbig2_image_set_pixel(image, x, y, bit);
}
}
@@ -135,9 +146,13 @@
char name[32];
snprintf(name, 32, "refin-%d.pbm", count);
- jbig2_image_write_pbm_file(ref, name);
+ code = jbig2_image_write_pbm_file(ref, name);
+ if (code < 0)
+ jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed to write refinement input");
snprintf(name, 32, "refout-%d.pbm", count);
- jbig2_image_write_pbm_file(image, name);
+ code = jbig2_image_write_pbm_file(image, name);
+ if (code < 0)
+ jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "failed to write refinement output");
count++;
}
#endif
@@ -159,6 +174,7 @@
byte *grreg_line = (byte *) image->data;
byte *grref_line = (byte *) params->reference->data;
int x, y;
+ int code = 0;
for (y = 0; y < GRH; y++) {
const int padded_width = (GRW + 7) & -8;
@@ -195,7 +211,9 @@
for (x_minor = 0; x_minor < minor_width; x_minor++) {
bool bit;
- bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+ bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement template1");
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x0d6) << 1) | bit |
((line_m1 >> (9 - x_minor)) & 0x002) |
@@ -281,7 +299,7 @@
}
static int
-jbig2_decode_refinement_TPGRON(const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
+jbig2_decode_refinement_TPGRON(Jbig2Ctx *ctx, const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
{
const int GRW = image->width;
const int GRH = image->height;
@@ -288,12 +306,17 @@
int x, y, iv, bit, LTP = 0;
uint32_t start_context = (params->GRTEMPLATE ? 0x40 : 0x100);
ContextBuilder mkctx = (params->GRTEMPLATE ? mkctx1 : mkctx0);
+ int code = 0;
for (y = 0; y < GRH; y++) {
- LTP ^= jbig2_arith_decode(as, &GR_stats[start_context]);
+ LTP ^= jbig2_arith_decode(as, &GR_stats[start_context], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
if (!LTP) {
for (x = 0; x < GRW; x++) {
- bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+ bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
jbig2_image_set_pixel(image, x, y, bit);
}
} else {
@@ -300,7 +323,9 @@
for (x = 0; x < GRW; x++) {
iv = implicit_value(params, image, x, y);
if (iv < 0) {
- bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+ bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
jbig2_image_set_pixel(image, x, y, bit);
} else
jbig2_image_set_pixel(image, x, y, iv);
@@ -340,7 +365,7 @@
}
if (params->TPGRON)
- return jbig2_decode_refinement_TPGRON(params, as, image, GR_stats);
+ return jbig2_decode_refinement_TPGRON(ctx, params, as, image, GR_stats);
if (params->GRTEMPLATE)
return jbig2_decode_refinement_template1_unopt(ctx, segment, params, as, image, GR_stats);
@@ -485,6 +510,10 @@
}
code = jbig2_decode_refinement_region(ctx, segment, ¶ms, as, image, GR_stats);
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to decode refinement region");
+ goto cleanup;
+ }
if ((segment->flags & 63) == 40) {
/* intermediate region. save the result for later */
@@ -493,7 +522,11 @@
/* immediate region. composite onto the page */
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"composing %dx%d decoded refinement region onto page at (%d, %d)", rsi.width, rsi.height, rsi.x, rsi.y);
- 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_WARNING, -1, "unable to add refinement region to page");
+ goto cleanup;
+ }
}
cleanup:
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -76,7 +76,7 @@
referred_to_segment_size = result->number <= 256 ? 1 : result->number <= 65536 ? 2 : 4; /* 7.2.5 */
pa_size = result->flags & 0x40 ? 4 : 1; /* 7.2.6 */
if (offset + referred_to_segment_count * referred_to_segment_size + pa_size + 4 > buf_size) {
- jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "jbig2_parse_segment_header() called with insufficient data", -1);
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, result->number, "jbig2_parse_segment_header() called with insufficient data", -1);
jbig2_free(ctx->allocator, result);
return NULL;
}
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -70,6 +70,7 @@
Jbig2SymbolDict *dict = (Jbig2SymbolDict *) segment->result;
int index;
char filename[24];
+ int code;
if (dict == NULL)
return;
@@ -78,10 +79,12 @@
snprintf(filename, sizeof(filename), "symbol_%02d-%04d.png", segment->number, index);
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "dumping symbol %d/%d as '%s'", index, dict->n_symbols, filename);
#ifdef HAVE_LIBPNG
- jbig2_image_write_png_file(dict->glyphs[index], filename);
+ code = jbig2_image_write_png_file(dict->glyphs[index], filename);
#else
- jbig2_image_write_pbm_file(dict->glyphs[index], filename);
+ code = jbig2_image_write_pbm_file(dict->glyphs[index], filename);
#endif
+ if (code < 0)
+ jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "failed to dump symbol %d/%d as '%s'", index, dict->n_symbols, filename);
}
}
#endif /* DUMP_SYMDICT */
@@ -318,7 +321,7 @@
if (params->SDHUFF) {
HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code);
} else {
- code = jbig2_arith_int_decode(IADH, as, &HCDH);
+ code = jbig2_arith_int_decode(ctx, IADH, as, &HCDH);
}
if (code != 0) {
@@ -350,7 +353,7 @@
if (params->SDHUFF) {
DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
} else {
- code = jbig2_arith_int_decode(IADW, as, &DW);
+ code = jbig2_arith_int_decode(ctx, IADW, as, &DW);
}
if (code < 0)
goto cleanup4;
@@ -415,7 +418,7 @@
if (params->SDHUFF) {
REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
} else {
- code = jbig2_arith_int_decode(IAAI, as, (int32_t *) & REFAGGNINST);
+ code = jbig2_arith_int_decode(ctx, IAAI, as, (int32_t *) & REFAGGNINST);
}
if (code || (int32_t) REFAGGNINST <= 0) {
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid number of symbols or OOB in aggregate glyph");
@@ -465,6 +468,14 @@
tparams->IARDH = jbig2_arith_int_ctx_new(ctx);
tparams->IARDX = jbig2_arith_int_ctx_new(ctx);
tparams->IARDY = jbig2_arith_int_ctx_new(ctx);
+ if ((tparams->IAID == NULL) || (tparams->IAFS == NULL) ||
+ (tparams->IADS == NULL) || (tparams->IAIT == NULL) ||
+ (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");
+ goto cleanup4;
+ }
} else {
tparams->SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F); /* Table B.6 */
tparams->SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H); /* Table B.8 */
@@ -473,6 +484,13 @@
tparams->SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
tparams->SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
tparams->SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
+ if ((tparams->SBHUFFFS == NULL) || (tparams->SBHUFFDS == NULL) ||
+ (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");
+ goto cleanup4;
+ }
}
tparams->SBHUFF = params->SDHUFF;
tparams->SBREFINE = 1;
@@ -522,9 +540,9 @@
BMSIZE = jbig2_huffman_get(hs, SBHUFFRSIZE, &code3);
jbig2_huffman_skip(hs);
} else {
- code1 = jbig2_arith_iaid_decode(IAID, as, (int32_t *) & ID);
- code2 = jbig2_arith_int_decode(IARDX, as, &RDX);
- code3 = jbig2_arith_int_decode(IARDY, as, &RDY);
+ code1 = jbig2_arith_iaid_decode(ctx, IAID, as, (int32_t *) & ID);
+ code2 = jbig2_arith_int_decode(ctx, IARDX, as, &RDX);
+ code3 = jbig2_arith_int_decode(ctx, IARDY, as, &RDY);
}
if ((code1 < 0) || (code2 < 0) || (code3 < 0) || (code4 < 0)) {
@@ -578,11 +596,15 @@
{
char name[64];
FILE *out;
+ int code;
snprintf(name, 64, "sd.%04d.%04d.pbm", segment->number, NSYMSDECODED);
out = fopen(name, "wb");
- jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
- jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "writing out glyph as '%s' ...", name);
+ code = jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
+ if (code < 0)
+ jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "failed to write glyph");
+ else
+ jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "writing out glyph as '%s' ...", name);
fclose(out);
}
#endif
@@ -682,7 +704,13 @@
jbig2_image_release(ctx, image);
goto cleanup4;
}
- jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
+ code = jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
+ if (code) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose image into glyph");
+ jbig2_image_release(ctx, glyph);
+ jbig2_image_release(ctx, image);
+ goto cleanup4;
+ }
x += SDNEWSYMWIDTHS[j];
SDNEWSYMS->glyphs[j] = glyph;
}
@@ -709,7 +737,7 @@
if (params->SDHUFF)
exrunlength = jbig2_huffman_get(hs, SBHUFFRSIZE, &code);
else
- code = jbig2_arith_int_decode(IAEX, as, (int32_t *)&exrunlength);
+ code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *)&exrunlength);
/* prevent infinite loop */
zerolength = exrunlength > 0 ? 0 : zerolength + 1;
if (code || (exrunlength > limit - i) || (zerolength > 4) || (exflag && (exrunlength + j > params->SDNUMEXSYMS))) {
--- a/jbig2_text.c
+++ b/jbig2_text.c
@@ -207,10 +207,12 @@
if (params->SBHUFF) {
STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
} else {
- code = jbig2_arith_int_decode(params->IADT, as, &STRIPT);
+ code = jbig2_arith_int_decode(ctx, params->IADT, as, &STRIPT);
}
- if (code < 0)
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain strip T");
goto cleanup2;
+ }
/* 6.4.5 (2) */
STRIPT *= -(params->SBSTRIPS);
@@ -223,10 +225,12 @@
if (params->SBHUFF) {
DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
} else {
- code = jbig2_arith_int_decode(params->IADT, as, &DT);
+ code = jbig2_arith_int_decode(ctx, params->IADT, as, &DT);
}
- if (code < 0)
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain delta T");
goto cleanup2;
+ }
DT *= params->SBSTRIPS;
STRIPT += DT;
@@ -239,10 +243,12 @@
if (params->SBHUFF) {
DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
} else {
- code = jbig2_arith_int_decode(params->IAFS, as, &DFS);
+ code = jbig2_arith_int_decode(ctx, params->IAFS, as, &DFS);
}
- if (code < 0)
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain strip symbol S-difference");
goto cleanup2;
+ }
FIRSTS += DFS;
CURS = FIRSTS;
first_symbol = FALSE;
@@ -255,7 +261,7 @@
if (params->SBHUFF) {
IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);
} else {
- code = jbig2_arith_int_decode(params->IADS, as, &IDS);
+ code = jbig2_arith_int_decode(ctx, params->IADS, as, &IDS);
}
if (code) {
/* decoded an OOB, reached end of strip */
@@ -270,10 +276,12 @@
} else if (params->SBHUFF) {
CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS, &code);
} else {
- code = jbig2_arith_int_decode(params->IAIT, as, &CURT);
+ code = jbig2_arith_int_decode(ctx, params->IAIT, as, &CURT);
}
- if (code < 0)
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance T coordinate");
goto cleanup2;
+ }
T = STRIPT + CURT;
/* (3b.iv) / 6.4.10 - decode the symbol id */
@@ -280,10 +288,12 @@
if (params->SBHUFF) {
ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
} else {
- code = jbig2_arith_iaid_decode(params->IAID, as, (int *)&ID);
+ code = jbig2_arith_iaid_decode(ctx, params->IAID, as, (int *)&ID);
}
- if (code < 0)
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");
goto cleanup2;
+ }
if (ID >= SBNUMSYMS) {
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol id out of range! (%d/%d)", ID, SBNUMSYMS);
goto cleanup2;
@@ -307,10 +317,12 @@
if (params->SBHUFF) {
RI = jbig2_huffman_get_bits(hs, 1, &code);
} else {
- code = jbig2_arith_int_decode(params->IARI, as, &RI);
+ code = jbig2_arith_int_decode(ctx, params->IARI, as, &RI);
}
- if (code < 0)
+ if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol bitmap refinement indicator");
goto cleanup2;
+ }
} else {
RI = 0;
}
@@ -328,10 +340,10 @@
/* 6.4.11 (1, 2, 3, 4) */
if (!params->SBHUFF) {
- code1 = jbig2_arith_int_decode(params->IARDW, as, &RDW);
- code2 = jbig2_arith_int_decode(params->IARDH, as, &RDH);
- code3 = jbig2_arith_int_decode(params->IARDX, as, &RDX);
- code4 = jbig2_arith_int_decode(params->IARDY, as, &RDY);
+ code1 = jbig2_arith_int_decode(ctx, params->IARDW, as, &RDW);
+ code2 = jbig2_arith_int_decode(ctx, params->IARDH, as, &RDH);
+ code3 = jbig2_arith_int_decode(ctx, params->IARDX, as, &RDX);
+ code4 = jbig2_arith_int_decode(ctx, params->IARDY, as, &RDY);
} else {
RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code1);
RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code2);
@@ -373,6 +385,7 @@
memcpy(rparams.grat, params->sbrat, 4);
code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, refimage, GR_stats);
if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
jbig2_image_release(ctx, refimage);
jbig2_image_release(ctx, IBO);
goto cleanup2;
@@ -448,6 +461,7 @@
#endif
code = jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP);
if (code < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose symbol instance symbol bitmap into picture");
jbig2_image_release(ctx, IB);
goto cleanup2;
}
@@ -877,7 +891,9 @@
/* otherwise composite onto the page */
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);
+ code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
+ if (code < 0)
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add text region to page");
}
cleanup4:
--- a/jbig2dec.c
+++ b/jbig2dec.c
@@ -333,12 +333,10 @@
switch (params->output_format) {
#ifdef HAVE_LIBPNG
case jbig2dec_format_png:
- jbig2_image_write_png(image, stdout);
- break;
+ return jbig2_image_write_png(image, stdout);
#endif
case jbig2dec_format_pbm:
- jbig2_image_write_pbm(image, stdout);
- break;
+ return jbig2_image_write_pbm(image, stdout);
default:
fprintf(stderr, "unsupported output format.\n");
return 1;
@@ -349,12 +347,10 @@
switch (params->output_format) {
#ifdef HAVE_LIBPNG
case jbig2dec_format_png:
- jbig2_image_write_png_file(image, params->output_file);
- break;
+ return jbig2_image_write_png_file(image, params->output_file);
#endif
case jbig2dec_format_pbm:
- jbig2_image_write_pbm_file(image, params->output_file);
- break;
+ return jbig2_image_write_pbm_file(image, params->output_file);
default:
fprintf(stderr, "unsupported output format.\n");
return 1;
@@ -391,6 +387,7 @@
jbig2dec_params_t params;
int filearg;
int result = 1;
+ int code;
/* set defaults */
params.mode = render;
@@ -449,6 +446,12 @@
}
ctx = jbig2_ctx_new(NULL, (Jbig2Options)(f_page != NULL ? JBIG2_OPTIONS_EMBEDDED : 0), NULL, error_callback, ¶ms);
+ if (ctx == NULL) {
+ fclose(f);
+ if (f_page)
+ fclose(f_page);
+ goto cleanup;
+ }
/* pull the whole file/global stream into memory */
for (;;) {
@@ -466,13 +469,15 @@
Jbig2GlobalCtx *global_ctx = jbig2_make_global_ctx(ctx);
ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, global_ctx, error_callback, ¶ms);
- for (;;) {
- int n_bytes = fread(buf, 1, sizeof(buf), f_page);
+ if (ctx != NULL) {
+ for (;;) {
+ int n_bytes = fread(buf, 1, sizeof(buf), f_page);
- if (n_bytes <= 0)
- break;
- if (jbig2_data_in(ctx, buf, n_bytes))
- break;
+ if (n_bytes <= 0)
+ break;
+ if (jbig2_data_in(ctx, buf, n_bytes))
+ break;
+ }
}
fclose(f_page);
jbig2_global_ctx_free(global_ctx);
@@ -484,7 +489,11 @@
/* work around broken CVision embedded streams */
if (f_page != NULL)
- jbig2_complete_page(ctx);
+ {
+ code = jbig2_complete_page(ctx);
+ if (code < 0)
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "unable to complete page");
+ }
if (params.output_file == NULL) {
#ifdef HAVE_LIBPNG
--- a/pbm2png.c
+++ b/pbm2png.c
@@ -39,7 +39,7 @@
{
Jbig2Ctx *ctx;
Jbig2Image *image;
- int error;
+ int code;
/* we need a context for the allocators */
ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL);
@@ -57,10 +57,10 @@
fprintf(stderr, "converting %dx%d image to png format\n", image->width, image->height);
}
- error = jbig2_image_write_png_file(image, argv[2]);
- if (error) {
- fprintf(stderr, "error writing png file '%s' error %d\n", argv[2], error);
+ code = jbig2_image_write_png_file(image, argv[2]);
+ if (code) {
+ fprintf(stderr, "error writing png file '%s' error %d\n", argv[2], code);
}
- return (error);
+ return (code);
}