shithub: jbig2

Download patch

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) */