ref: 8acccc58c83123286b0954053a7dd899de5a0630
parent: e2ff5e373bd8ecda6db43c6b6414c8a3f3248297
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Mon Aug 29 22:05:05 EDT 2005
Fix some small bugs and add additional error checking to the huffman decoding support. git-svn-id: http://svn.ghostscript.com/jbig2dec/trunk@434 ded80894-8fb9-0310-811b-c03f3676ab4d
--- a/jbig2_huffman.c
+++ b/jbig2_huffman.c
@@ -90,10 +90,9 @@
/** debug routines **/
#ifdef JBIG2_DEBUG
-#include <stdio.h>
+
/** print current huffman state */
-void jbig2_dump_huffman_state(Jbig2HuffmanState *hs)
-{
+void jbig2_dump_huffman_state(Jbig2HuffmanState *hs) {
fprintf(stderr, "huffman state %08x %08x offset %d.%d\n",
hs->this_word, hs->next_word, hs->offset, hs->offset_bits);
}
@@ -109,6 +108,7 @@
fprintf(stderr, ((word >> i) & 1) ? "1" : "0");
fprintf(stderr, "\n");
}
+
#endif /* JBIG2_DEBUG */
/** Skip bits up to the next byte boundary
@@ -174,7 +174,7 @@
{
uint32_t this_word = hs->this_word;
int32_t result;
-
+
result = this_word >> (32 - bits);
hs->offset_bits += bits;
if (hs->offset_bits >= 32) {
@@ -182,8 +182,12 @@
hs->offset_bits -= 32;
hs->this_word = hs->next_word;
hs->next_word = hs->ws->get_next_word(hs->ws, hs->offset + 4);
- hs->this_word = (hs->this_word << hs->offset_bits) |
+ if (hs->offset_bits) {
+ hs->this_word = (hs->this_word << hs->offset_bits) |
(hs->next_word >> (32 - hs->offset_bits));
+ } else {
+ hs->this_word = (hs->this_word << hs->offset_bits);
+ }
} else {
hs->this_word = (this_word << bits) |
(hs->next_word >> (32 - hs->offset_bits));
@@ -225,9 +229,9 @@
hs->next_word = next_word;
PREFLEN = offset_bits;
}
-if (PREFLEN)
- this_word = (this_word << PREFLEN) |
- (next_word >> (32 - offset_bits));
+ if (PREFLEN)
+ this_word = (this_word << PREFLEN) |
+ (next_word >> (32 - offset_bits));
if (flags & JBIG2_HUFFMAN_FLAGS_ISEXT)
{
table = entry->u.ext_table;
@@ -272,10 +276,10 @@
return result;
}
-/* TODO: 10 bits here is wasteful of memory. We have support for
- sub-trees in jbig2_huffman_get() above, but don't use it here.
+/* TODO: more than 8 bits here is wasteful of memory. We have support
+ for sub-trees in jbig2_huffman_get() above, but don't use it here.
We should, and then revert to 8 bits */
-#define LOG_TABLE_SIZE_MAX 10
+#define LOG_TABLE_SIZE_MAX 16
/** Build an in-memory representation of a Huffman table from the
* set of template params provided by the spec or a table segment
@@ -288,6 +292,7 @@
const Jbig2HuffmanLine *lines = params->lines;
int n_lines = params->n_lines;
int i, j;
+ int max_j;
int log_table_size = 0;
Jbig2HuffmanTable *result;
Jbig2HuffmanEntry *entries;
@@ -316,9 +321,13 @@
if (lts <= LOG_TABLE_SIZE_MAX && log_table_size < lts)
log_table_size = lts;
}
+ jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
+ "constructing huffman table log size %d", log_table_size);
+ max_j = 1 << log_table_size;
+
result = (Jbig2HuffmanTable *)jbig2_alloc(ctx->allocator, sizeof(Jbig2HuffmanTable));
result->log_table_size = log_table_size;
- entries = (Jbig2HuffmanEntry *)jbig2_alloc(ctx->allocator, sizeof(Jbig2HuffmanEntry) << log_table_size);
+ entries = (Jbig2HuffmanEntry *)jbig2_alloc(ctx->allocator, max_j * sizeof(Jbig2HuffmanEntry));
result->entries = entries;
LENCOUNT[0] = 0;
@@ -341,25 +350,28 @@
int end_j = (CURCODE + 1) << shift;
byte eflags = 0;
+ if (end_j > max_j) {
+ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+ "ran off the end of the entries table! (%d >= %d)",
+ end_j, max_j);
+ jbig2_free(ctx->allocator, result->entries);
+ jbig2_free(ctx->allocator, result);
+ return NULL;
+ }
/* todo: build extension tables */
if (params->HTOOB && CURTEMP == n_lines - 1)
eflags |= JBIG2_HUFFMAN_FLAGS_ISOOB;
if (CURTEMP == n_lines - (params->HTOOB ? 3 : 2))
eflags |= JBIG2_HUFFMAN_FLAGS_ISLOW;
- if (PREFLEN + RANGELEN > LOG_TABLE_SIZE_MAX)
- {
- for (j = start_j; j < end_j; j++)
- {
+ if (PREFLEN + RANGELEN > LOG_TABLE_SIZE_MAX) {
+ for (j = start_j; j < end_j; j++) {
entries[j].u.RANGELOW = lines[CURTEMP].RANGELOW;
entries[j].PREFLEN = PREFLEN;
entries[j].RANGELEN = RANGELEN;
entries[j].flags = eflags;
}
- }
- else
- {
- for (j = start_j; j < end_j; j++)
- {
+ } else {
+ for (j = start_j; j < end_j; j++) {
int32_t HTOFFSET = (j >> (shift - RANGELEN)) &
((1 << RANGELEN) - 1);
if (eflags & JBIG2_HUFFMAN_FLAGS_ISLOW)
--- a/jbig2_text.c
+++ b/jbig2_text.c
@@ -187,7 +187,6 @@
/* decode the symbol id codelengths using the runlength table */
symcodelengths = jbig2_alloc(ctx->allocator, SBNUMSYMS*sizeof(Jbig2HuffmanLine));
- /* todo: could save considerable space by growing the lines array as needed */
if (symcodelengths == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"memory allocation failure reading symbol ID huffman table!");
@@ -213,23 +212,30 @@
return -1;
}
len = symcodelengths[index-1].PREFLEN;
- if (code == 32) range = jbig2_huffman_get_bits(hs, 2) + 3;
+ if (code == 32) range = jbig2_huffman_get_bits(hs, 2) + 2;
else if (code == 33) range = jbig2_huffman_get_bits(hs, 3) + 3;
else if (code == 34) range = jbig2_huffman_get_bits(hs, 7) + 11;
}
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
" read runcode%d at index %d (length %d range %d)", code, index, len, range);
+ if (index+range > SBNUMSYMS) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "runlength extends %d entries beyond the end of symbol id table!",
+ index+range - SBNUMSYMS);
+ range = SBNUMSYMS - index;
+ }
for (r = 0; r < range; r++) {
symcodelengths[index+r].PREFLEN = len;
symcodelengths[index+r].RANGELEN = 0;
- symcodelengths[index+r].RANGELOW = index;
+ symcodelengths[index+r].RANGELOW = index + r;
}
index += r;
- if (index > SBNUMSYMS) {
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
- "runlength extends beyond the end of symbol id table");
- }
}
+
+ if (index < SBNUMSYMS) {
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+ "runlength codes do not cover the available symbol set");
+ }
symcodeparams.HTOOB = 0;
symcodeparams.lines = symcodelengths;
symcodeparams.n_lines = SBNUMSYMS;
@@ -242,6 +248,12 @@
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 NULL;
+ }
}
/* 6.4.5 (1) */