summaryrefslogtreecommitdiff
path: root/jbig2dec
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2019-09-15 19:01:05 +0200
committerSebastian Rasmussen <sebras@gmail.com>2020-03-20 17:56:04 +0800
commitcd1ef5475a3bda7a97851abc679c75e2ee64dec3 (patch)
tree48f44d7bd191a88f086cab7733417bb091220088 /jbig2dec
parent30842ee99923fa10a7301494fd08b998e7acf57b (diff)
downloadghostpdl-cd1ef5475a3bda7a97851abc679c75e2ee64dec3.tar.gz
Bug 702165: jbig2dec: Treat end of stream as fatal error, and remember errors.
* Treat reading beyond end of stream in arithmetic decoder as a fatal error. * Remember previously encountered stream errors in arithmetic decoder. * Ignore trailing bytes after terminating marker code in stream.
Diffstat (limited to 'jbig2dec')
-rw-r--r--jbig2dec/jbig2_arith.c76
-rw-r--r--jbig2dec/jbig2_huffman.c4
2 files changed, 54 insertions, 26 deletions
diff --git a/jbig2dec/jbig2_arith.c b/jbig2dec/jbig2_arith.c
index 8c40f6985..6ce00e693 100644
--- a/jbig2dec/jbig2_arith.c
+++ b/jbig2dec/jbig2_arith.c
@@ -56,10 +56,19 @@ struct _Jbig2ArithState {
static int
jbig2_arith_bytein(Jbig2Ctx *ctx, Jbig2ArithState *as)
{
- int new_bytes;
byte B;
- /* invariant: as->next_word_bytes > 0 */
+ /* Treat both errors and reading beyond end of stream as an error. */
+ if (as->next_word_bytes < 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to read from underlying stream during arithmetic decoding");
+ return -1;
+ }
+ if (as->next_word_bytes == 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to read beyond end of underlying stream during arithmetic decoding");
+ return -1;
+ }
+
+ /* At this point there is at least one byte in as->next_word. */
/* This code confused me no end when I first read it, so a quick note
* to save others (and future me's) from being similarly confused.
@@ -83,15 +92,22 @@ jbig2_arith_bytein(Jbig2Ctx *ctx, Jbig2ArithState *as)
if (B == 0xFF) {
byte B1;
- if (as->next_word_bytes == 1) {
- Jbig2WordStream *ws = as->ws;
-
- new_bytes = ws->get_next_word(ctx, ws, as->offset, &as->next_word);
- if (new_bytes < 0) {
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read from underlying stream during arithmetic decoding");
+ /* next_word_bytes can only be == 1 here, but let's be defensive. */
+ if (as->next_word_bytes <= 1) {
+ as->next_word_bytes = as->ws->get_next_word(ctx, as->ws, as->offset, &as->next_word);
+ if (as->next_word_bytes < 0) {
+ return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to check for marker code due to failure in underlying stream during arithmetic decoding");
+ }
+ if (as->next_word_bytes == 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read end of possible terminating marker code, assuming terminating marker code");
+ as->next_word = 0xFF900000;
+ as->next_word_bytes = 2;
+ as->C += 0xFF00;
+ as->CT = 8;
+ return 0;
}
- as->next_word_bytes = new_bytes;
- as->offset += new_bytes;
+
+ as->offset += as->next_word_bytes;
B1 = (byte)((as->next_word >> 24) & 0xFF);
if (B1 > 0x8F) {
@@ -100,7 +116,7 @@ jbig2_arith_bytein(Jbig2Ctx *ctx, Jbig2ArithState *as)
#endif
as->CT = 8;
as->next_word = 0xFF000000 | (as->next_word >> 8);
- as->next_word_bytes = 4;
+ as->next_word_bytes = 2;
as->offset--;
} else {
#ifdef JBIG2_DEBUG_ARITH
@@ -131,21 +147,29 @@ jbig2_arith_bytein(Jbig2Ctx *ctx, Jbig2ArithState *as)
#ifdef JBIG2_DEBUG_ARITH
fprintf(stderr, "read %02x\n", B);
#endif
- as->CT = 8;
as->next_word <<= 8;
as->next_word_bytes--;
- if (as->next_word_bytes == 0) {
- Jbig2WordStream *ws = as->ws;
- new_bytes = ws->get_next_word(ctx, ws, as->offset, &as->next_word);
- if (new_bytes < 0) {
+ if (as->next_word_bytes == 0) {
+ as->next_word_bytes = as->ws->get_next_word(ctx, as->ws, as->offset, &as->next_word);
+ if (as->next_word_bytes < 0) {
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read from underlying stream during arithmetic decoding");
}
- as->offset += new_bytes;
- as->next_word_bytes = new_bytes;
+ if (as->next_word_bytes == 0) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to find terminating marker code before end of underlying stream, assuming terminating marker code");
+ as->next_word = 0xFF900000;
+ as->next_word_bytes = 2;
+ as->C += 0xFF00;
+ as->CT = 8;
+ return 0;
+ }
+
+ as->offset += as->next_word_bytes;
}
+
B = (byte)((as->next_word >> 24) & 0xFF);
as->C += 0xFF00 - (B << 8);
+ as->CT = 8;
}
return 0;
@@ -159,7 +183,6 @@ Jbig2ArithState *
jbig2_arith_new(Jbig2Ctx *ctx, Jbig2WordStream *ws)
{
Jbig2ArithState *result;
- int new_bytes;
result = jbig2_new(ctx, Jbig2ArithState, 1);
if (result == NULL) {
@@ -168,15 +191,20 @@ jbig2_arith_new(Jbig2Ctx *ctx, Jbig2WordStream *ws)
}
result->ws = ws;
+ result->offset = 0;
- new_bytes = ws->get_next_word(ctx, ws, 0, &result->next_word);
- if (new_bytes < 0) {
+ result->next_word_bytes = result->ws->get_next_word(ctx, result->ws, result->offset, &result->next_word);
+ if (result->next_word_bytes < 0) {
+ jbig2_free(ctx->allocator, result);
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to initialize underlying stream of arithmetic decoder");
+ return NULL;
+ }
+ if (result->next_word_bytes == 0) {
jbig2_free(ctx->allocator, result);
- jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to initialize underlying stream of arithmetic decoder");
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to read first byte from underlying stream when initializing arithmetic decoder");
return NULL;
}
- result->next_word_bytes = new_bytes;
- result->offset = new_bytes;
+ result->offset += result->next_word_bytes;
/* Figure F.1 */
result->C = (~(result->next_word >> 8)) & 0xFF0000;
diff --git a/jbig2dec/jbig2_huffman.c b/jbig2dec/jbig2_huffman.c
index 8139495cc..59bf8b223 100644
--- a/jbig2dec/jbig2_huffman.c
+++ b/jbig2dec/jbig2_huffman.c
@@ -80,13 +80,13 @@ jbig2_huffman_new(Jbig2Ctx *ctx, Jbig2WordStream *ws)
result->ctx = ctx;
code = huff_get_next_word(result, 0, &result->this_word);
if (code < 0) {
- jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed read first huffman word");
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read first huffman word");
jbig2_huffman_free(ctx, result);
return NULL;
}
code = huff_get_next_word(result, 4, &result->next_word);
if (code < 0) {
- jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed read second huffman word");
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to read second huffman word");
jbig2_huffman_free(ctx, result);
return NULL;
}