shithub: jbig2

Download patch

ref: d50d2bbd939654edb7275c19843de02ae0d37e4d
parent: 55c69896eaa11f2ff55cbe507884869247272ade
author: Sebastian Rasmussen <[email protected]>
date: Mon May 28 23:09:58 EDT 2018

jbig2dec: Limit image size to 2GByte and check for overflow.

The width/height fields of a JBIG2 image are limited by the
specification to UINT32_MAX. This means that the total size of
the image is limited to UINT32_MAX * UINT32_MAX pixels.

jbig2_alloc() take a size argument of type size_t, limiting
allocations to at most SIZE_MAX bytes. For 32 bit systems
SIZE_MAX == UINT32_MAX and for 64 bit systems SIZE_MAX ==
UINT64_MAX.

This means that for 32 bit systems the maximum image size is
limited to UINT32_MAX * 8 pixels. For 64 bit systems it could
conceivably be limited to UINT64_MAX * 8 pixels if all indexing
into the image buffer allocation is 64 bit safe.

However jbig2dec's indexing into the image buffer allocations is
not always 64 bit safe, so limit image allocations to the safe
choice of 2Gbyte. This equates to limiting image sizes to
INT32_MAX * 8 pixels, or a square of 131072 by 131072 pixels.

--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -30,6 +30,10 @@
 #include "jbig2_priv.h"
 #include "jbig2_image.h"
 
+#if !defined (INT32_MAX)
+#define INT32_MAX  0x7fffffff
+#endif
+
 /* allocate a Jbig2Image structure and its associated bitmap */
 Jbig2Image *
 jbig2_image_new(Jbig2Ctx *ctx, uint32_t width, uint32_t height)
@@ -36,7 +40,6 @@
 {
     Jbig2Image *image;
     uint32_t stride;
-    int64_t check;
 
     if (width == 0 || height == 0) {
         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
@@ -52,16 +55,16 @@
     }
 
     stride = ((width - 1) >> 3) + 1;    /* generate a byte-aligned stride */
+
     /* check for integer multiplication overflow */
-    check = ((int64_t) stride) * ((int64_t) height);
-    if (check != (int)check) {
-        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "integer multiplication overflow from stride(%d)*height(%d)", stride, height);
+    if (height > (INT32_MAX / stride)) {
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "integer multiplication overflow stride=%u, height=%u", stride, height);
         jbig2_free(ctx->allocator, image);
         return NULL;
     }
-    image->data = jbig2_new(ctx, uint8_t, (int)check);
+    image->data = jbig2_new(ctx, uint8_t, (size_t) height * stride);
     if (image->data == NULL) {
-        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "could not allocate image data buffer! [stride(%d)*height(%d) bytes]", stride, height);
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "could not allocate image data buffer! [stride(%u)*height(%u) bytes]", stride, height);
         jbig2_free(ctx->allocator, image);
         return NULL;
     }
@@ -110,14 +113,12 @@
 {
     if (width == image->width) {
         /* check for integer multiplication overflow */
-        int64_t check = ((int64_t) image->stride) * ((int64_t) height);
-
-        if (check != (int)check) {
-            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "integer multiplication overflow during resize stride(%d)*height(%d)", image->stride, height);
+        if (image->height > (INT32_MAX / image->stride)) {
+            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "integer multiplication overflow during resize stride(%u)*height(%u)", image->stride, height);
             return NULL;
         }
         /* use the same stride, just change the length */
-        image->data = jbig2_renew(ctx, image->data, uint8_t, (int)check);
+        image->data = jbig2_renew(ctx, image->data, uint8_t, (size_t) height * image->stride);
         if (image->data == NULL) {
             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "could not resize image buffer");
             return NULL;
@@ -124,7 +125,7 @@
         }
         if (height > image->height) {
             const uint8_t fill = value ? 0xFF : 0x00;
-            memset(image->data + image->height * image->stride, fill, (height - image->height) * image->stride);
+            memset(image->data + (size_t) image->height * image->stride, fill, ((size_t) height - image->height) * image->stride);
         }
         image->height = height;
 
@@ -323,8 +324,10 @@
     /* general OR case */
     s = ss;
     d = dd = dst->data + y * dst->stride + leftbyte;
-    if (d < dst->data || leftbyte > dst->stride || d - leftbyte + h * dst->stride > dst->data + dst->height * dst->stride ||
-            s - leftbyte + (h - 1) * src->stride + rightbyte > src->data + src->height * src->stride) {
+    if (d < dst->data ||
+        leftbyte > dst->stride ||
+        d - leftbyte + (size_t) h * dst->stride > dst->data + (size_t) dst->height * dst->stride ||
+        s - leftbyte + (size_t) (h - 1) * src->stride + rightbyte > src->data + (size_t) src->height * src->stride) {
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "preventing heap overflow in jbig2_image_compose");
     }
     if (leftbyte == rightbyte) {