shithub: jbig2

Download patch

ref: 6e1f2259115efac14cd6c7ad9d119b43013a32a1
parent: d6dcc6bd175300af5cc71c8395207a4ec67c2d0c
author: Simon Bünzli <[email protected]>
date: Tue Jan 14 17:45:49 EST 2014

Bug 694949: prevent denial of service with arithmetic decoding

Badly constructed Jbig2 images using arithmetic decoding may result in
a denial of service attack by causing huge images to be created and
initialized from no data at all (at EOS, the arithmetic decoder always
returns the same values instead of failing).

Two cases are prevented with this patch:
* huge generic regions with barely any data to decode it from
* a huge list of height classes with no data at all to decode it from

This can be seen e.g. in:

b534b5caad95dd405735ec9a079fd43b_asan_heap-oob_14bf3ce_6977_5690.pdf

Thanks to Mateusz Jurczyk and Gynvael Coldwind of the Google Security
Team for providing the example files.

--- a/jbig2_arith.c
+++ b/jbig2_arith.c
@@ -379,6 +379,12 @@
     }
 }
 
+int
+jbig2_arith_get_offset(Jbig2ArithState *as)
+{
+  return as->offset;
+}
+
 #ifdef TEST
 
 static int
--- a/jbig2_arith.h
+++ b/jbig2_arith.h
@@ -33,4 +33,6 @@
 bool
 jbig2_arith_decode (Jbig2ArithState *as, Jbig2ArithCx *pcx);
 
-
+/* return the state's offset (for sanity checks) */
+int
+jbig2_arith_get_offset(Jbig2ArithState *as);
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -760,6 +760,12 @@
 {
   const int8_t *gbat = params->gbat;
 
+  if (image->stride * image->height > (1 << 24) && segment->data_length < image->stride * image->height / 256) {
+    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+                       "region is far larger than data provided (%d << %d), aborting to prevent DOS",
+                       segment->data_length, image->stride * image->height);
+  }
+
   if (!params->MMR && params->TPGDON) 
      return jbig2_decode_generic_region_TPGDON(ctx, segment, params, 
 		as, image, GB_stats);
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -361,6 +361,12 @@
 	  "error or OOB decoding height class delta (%d)\n", code);
       }
 
+      if (!params->SDHUFF && jbig2_arith_get_offset(as) >= size) {
+          code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+              "prevent DOS while decoding height classes");
+          goto cleanup2;
+      }
+
       /* 6.5.5 (4b) */
       HCHEIGHT = HCHEIGHT + HCDH;
       SYMWIDTH = 0;