diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2019-09-15 19:01:05 +0200 |
---|---|---|
committer | Sebastian Rasmussen <sebras@gmail.com> | 2020-03-20 17:56:04 +0800 |
commit | cd1ef5475a3bda7a97851abc679c75e2ee64dec3 (patch) | |
tree | 48f44d7bd191a88f086cab7733417bb091220088 /jbig2dec | |
parent | 30842ee99923fa10a7301494fd08b998e7acf57b (diff) | |
download | ghostpdl-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.c | 76 | ||||
-rw-r--r-- | jbig2dec/jbig2_huffman.c | 4 |
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; } |