Blame SOURCES/0032-CVE-2022-2867-CVE-2022-2868-tiffcrop.c-Fix-issue-352.patch

b45dc8
From 5d214a07db3bb8dcea8354d8f1e52f9c46264acb Mon Sep 17 00:00:00 2001
b45dc8
From: Su Laus <sulau@freenet.de>
b45dc8
Date: Wed, 9 Feb 2022 21:31:29 +0000
b45dc8
Subject: [PATCH] (CVE-2022-2867 CVE-2022-2868) tiffcrop.c: Fix issue #352
b45dc8
 heap-buffer-overflow by correcting uint32_t underflow.
b45dc8
b45dc8
(cherry picked from commit 07d79fcac2ead271b60e32aeb80f7b4f3be9ac8c)
b45dc8
---
b45dc8
 tools/tiffcrop.c | 81 +++++++++++++++++++++++++++++++-----------------
b45dc8
 1 file changed, 53 insertions(+), 28 deletions(-)
b45dc8
b45dc8
diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c
b45dc8
index ea0b98be..5801b8f6 100644
b45dc8
--- a/tools/tiffcrop.c
b45dc8
+++ b/tools/tiffcrop.c
b45dc8
@@ -5152,29 +5152,45 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image,
b45dc8
 	y1 = _TIFFClampDoubleToUInt32(crop->corners[i].Y1);
b45dc8
 	y2 = _TIFFClampDoubleToUInt32(crop->corners[i].Y2);
b45dc8
 	}
b45dc8
-      if (x1 < 1)
b45dc8
-        crop->regionlist[i].x1 = 0;
b45dc8
-      else
b45dc8
-        crop->regionlist[i].x1 = (uint32) (x1 - 1);
b45dc8
+      /* a) Region needs to be within image sizes 0.. width-1; 0..length-1 
b45dc8
+       * b) Corners are expected to be submitted as top-left to bottom-right.
b45dc8
+       *    Therefore, check that and reorder input.
b45dc8
+       * (be aware x,y are already casted to (uint32_t) and avoid (0 - 1) )
b45dc8
+       */
b45dc8
+      uint32 aux;
b45dc8
+      if (x1 > x2) {
b45dc8
+        aux = x1;
b45dc8
+        x1 = x2;
b45dc8
+        x2 = aux;
b45dc8
+      }
b45dc8
+      if (y1 > y2) {
b45dc8
+        aux = y1;
b45dc8
+        y1 = y2;
b45dc8
+        y2 = aux;
b45dc8
+      }
b45dc8
+      if (x1 > image->width - 1)
b45dc8
+        crop->regionlist[i].x1 = image->width - 1;
b45dc8
+      else if (x1 > 0)
b45dc8
+        crop->regionlist[i].x1 = (uint32)(x1 - 1);
b45dc8
 
b45dc8
       if (x2 > image->width - 1)
b45dc8
         crop->regionlist[i].x2 = image->width - 1;
b45dc8
-      else
b45dc8
-        crop->regionlist[i].x2 = (uint32) (x2 - 1);
b45dc8
-      zwidth  = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1; 
b45dc8
+      else if (x2 > 0)
b45dc8
+        crop->regionlist[i].x2 = (uint32)(x2 - 1);
b45dc8
 
b45dc8
-      if (y1 < 1)
b45dc8
-        crop->regionlist[i].y1 = 0;
b45dc8
-      else
b45dc8
-        crop->regionlist[i].y1 = (uint32) (y1 - 1);
b45dc8
+      zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1;
b45dc8
+
b45dc8
+      if (y1 > image->length - 1)
b45dc8
+        crop->regionlist[i].y1 = image->length - 1;
b45dc8
+      else if (y1 > 0)
b45dc8
+        crop->regionlist[i].y1 = (uint32)(y1 - 1);
b45dc8
 
b45dc8
       if (y2 > image->length - 1)
b45dc8
         crop->regionlist[i].y2 = image->length - 1;
b45dc8
-      else
b45dc8
-        crop->regionlist[i].y2 = (uint32) (y2 - 1);
b45dc8
-
b45dc8
-      zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1; 
b45dc8
+      else if (y2 > 0)
b45dc8
+        crop->regionlist[i].y2 = (uint32)(y2 - 1);
b45dc8
 
b45dc8
+      zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
b45dc8
       if (zwidth > max_width)
b45dc8
         max_width = zwidth;
b45dc8
       if (zlength > max_length)
b45dc8
@@ -5204,7 +5220,7 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image,
b45dc8
 	}
b45dc8
       }
b45dc8
     return (0);
b45dc8
-    }
b45dc8
+    }  /* crop_mode == CROP_REGIONS */
b45dc8
   
b45dc8
   /* Convert crop margins into offsets into image
b45dc8
    * Margins are expressed as pixel rows and columns, not bytes
b45dc8
@@ -5240,7 +5256,7 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image,
b45dc8
       bmargin = (uint32) 0;
b45dc8
       return (-1);
b45dc8
       }
b45dc8
-    }
b45dc8
+    }  /* crop_mode == CROP_MARGINS */
b45dc8
   else
b45dc8
     { /* no margins requested */
b45dc8
     tmargin = (uint32) 0;
b45dc8
@@ -5331,24 +5347,23 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image,
b45dc8
   off->endx   = endx;
b45dc8
   off->endy   = endy;
b45dc8
 
b45dc8
-  crop_width  = endx - startx + 1;
b45dc8
-  crop_length = endy - starty + 1;
b45dc8
-
b45dc8
-  if (crop_width <= 0)
b45dc8
+  if (endx + 1 <= startx)
b45dc8
     {
b45dc8
     TIFFError("computeInputPixelOffsets", 
b45dc8
                "Invalid left/right margins and /or image crop width requested");
b45dc8
     return (-1);
b45dc8
     }
b45dc8
+  crop_width  = endx - startx + 1;
b45dc8
   if (crop_width > image->width)
b45dc8
     crop_width = image->width;
b45dc8
 
b45dc8
-  if (crop_length <= 0)
b45dc8
+  if (endy + 1 <= starty)
b45dc8
     {
b45dc8
     TIFFError("computeInputPixelOffsets", 
b45dc8
               "Invalid top/bottom margins and /or image crop length requested");
b45dc8
     return (-1);
b45dc8
     }
b45dc8
+  crop_length = endy - starty + 1;
b45dc8
   if (crop_length > image->length)
b45dc8
     crop_length = image->length;
b45dc8
 
b45dc8
@@ -5448,10 +5463,17 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
b45dc8
   else
b45dc8
     crop->selections = crop->zones;
b45dc8
 
b45dc8
-  for (i = 0; i < crop->zones; i++)
b45dc8
+  /* Initialize regions iterator i */
b45dc8
+  i = 0;
b45dc8
+  for (int j = 0; j < crop->zones; j++)
b45dc8
     {
b45dc8
-    seg = crop->zonelist[i].position;
b45dc8
-    total = crop->zonelist[i].total;
b45dc8
+    seg = crop->zonelist[j].position;
b45dc8
+    total = crop->zonelist[j].total;
b45dc8
+
b45dc8
+    /* check for not allowed zone cases like 0:0; 4:3; etc. and skip that input */
b45dc8
+    if (seg == 0 || total == 0 || seg > total) {
b45dc8
+        continue;
b45dc8
+    }
b45dc8
 
b45dc8
     switch (crop->edge_ref) 
b45dc8
       {
b45dc8
@@ -5578,10 +5600,13 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
b45dc8
   if (dump->outfile != NULL)
b45dc8
     dump_info (dump->outfile, dump->format, "",  "Zone %d, width: %4d, length: %4d, x1: %4d  x2: %4d  y1: %4d  y2: %4d",
b45dc8
                     i + 1, (uint32)zwidth, (uint32)zlength,
b45dc8
-		    crop->regionlist[i].x1, crop->regionlist[i].x2, 
b45dc8
-                    crop->regionlist[i].y1, crop->regionlist[i].y2);
b45dc8
+               crop->regionlist[i].x1, crop->regionlist[i].x2,
b45dc8
+               crop->regionlist[i].y1, crop->regionlist[i].y2);
b45dc8
+  /* increment regions iterator */
b45dc8
+  i++;
b45dc8
     }
b45dc8
-
b45dc8
+    /* set number of generated regions out of given zones */
b45dc8
+    crop->selections = i;
b45dc8
   return (0);
b45dc8
   } /* end getCropOffsets */
b45dc8