1From 6cfe933df4dbac5479801b2bd10103ef7db815ee Mon Sep 17 00:00:00 2001 2From: 4ugustus <wangdw.augustus@qq.com> 3Date: Sat, 11 Jun 2022 09:31:43 +0000 4Subject: [PATCH] fix the FPE in tiffcrop (#415, #427, and #428) 5 6CVE: CVE-2022-2056 CVE-2022-2057 CVE-2022-2058 7Upstream-Status: Backport 8Signed-off-by: Ross Burton <ross.burton@arm.com> 9Signed-off-by: Steve Sakoman <steve@sakoman.com> 10 11--- 12 libtiff/tif_aux.c | 9 +++++++ 13 libtiff/tiffiop.h | 1 + 14 tools/tiffcrop.c | 62 ++++++++++++++++++++++++++--------------------- 15 3 files changed, 44 insertions(+), 28 deletions(-) 16 17diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c 18index 140f26c..5b88c8d 100644 19--- a/libtiff/tif_aux.c 20+++ b/libtiff/tif_aux.c 21@@ -402,6 +402,15 @@ float _TIFFClampDoubleToFloat( double val ) 22 return (float)val; 23 } 24 25+uint32_t _TIFFClampDoubleToUInt32(double val) 26+{ 27+ if( val < 0 ) 28+ return 0; 29+ if( val > 0xFFFFFFFFU || val != val ) 30+ return 0xFFFFFFFFU; 31+ return (uint32_t)val; 32+} 33+ 34 int _TIFFSeekOK(TIFF* tif, toff_t off) 35 { 36 /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */ 37diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h 38index f1151f5..c1d0276 100644 39--- a/libtiff/tiffiop.h 40+++ b/libtiff/tiffiop.h 41@@ -368,6 +368,7 @@ extern double _TIFFUInt64ToDouble(uint64_t); 42 extern float _TIFFUInt64ToFloat(uint64_t); 43 44 extern float _TIFFClampDoubleToFloat(double); 45+extern uint32_t _TIFFClampDoubleToUInt32(double); 46 47 extern tmsize_t 48 _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32_t strip, 49diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c 50index e407bf5..b9b13d8 100644 51--- a/tools/tiffcrop.c 52+++ b/tools/tiffcrop.c 53@@ -5182,17 +5182,17 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image, 54 { 55 if ((crop->res_unit == RESUNIT_INCH) || (crop->res_unit == RESUNIT_CENTIMETER)) 56 { 57- x1 = (uint32_t) (crop->corners[i].X1 * scale * xres); 58- x2 = (uint32_t) (crop->corners[i].X2 * scale * xres); 59- y1 = (uint32_t) (crop->corners[i].Y1 * scale * yres); 60- y2 = (uint32_t) (crop->corners[i].Y2 * scale * yres); 61+ x1 = _TIFFClampDoubleToUInt32(crop->corners[i].X1 * scale * xres); 62+ x2 = _TIFFClampDoubleToUInt32(crop->corners[i].X2 * scale * xres); 63+ y1 = _TIFFClampDoubleToUInt32(crop->corners[i].Y1 * scale * yres); 64+ y2 = _TIFFClampDoubleToUInt32(crop->corners[i].Y2 * scale * yres); 65 } 66 else 67 { 68- x1 = (uint32_t) (crop->corners[i].X1); 69- x2 = (uint32_t) (crop->corners[i].X2); 70- y1 = (uint32_t) (crop->corners[i].Y1); 71- y2 = (uint32_t) (crop->corners[i].Y2); 72+ x1 = _TIFFClampDoubleToUInt32(crop->corners[i].X1); 73+ x2 = _TIFFClampDoubleToUInt32(crop->corners[i].X2); 74+ y1 = _TIFFClampDoubleToUInt32(crop->corners[i].Y1); 75+ y2 = _TIFFClampDoubleToUInt32(crop->corners[i].Y2); 76 } 77 if (x1 < 1) 78 crop->regionlist[i].x1 = 0; 79@@ -5255,17 +5255,17 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image, 80 { 81 if (crop->res_unit != RESUNIT_INCH && crop->res_unit != RESUNIT_CENTIMETER) 82 { /* User has specified pixels as reference unit */ 83- tmargin = (uint32_t)(crop->margins[0]); 84- lmargin = (uint32_t)(crop->margins[1]); 85- bmargin = (uint32_t)(crop->margins[2]); 86- rmargin = (uint32_t)(crop->margins[3]); 87+ tmargin = _TIFFClampDoubleToUInt32(crop->margins[0]); 88+ lmargin = _TIFFClampDoubleToUInt32(crop->margins[1]); 89+ bmargin = _TIFFClampDoubleToUInt32(crop->margins[2]); 90+ rmargin = _TIFFClampDoubleToUInt32(crop->margins[3]); 91 } 92 else 93 { /* inches or centimeters specified */ 94- tmargin = (uint32_t)(crop->margins[0] * scale * yres); 95- lmargin = (uint32_t)(crop->margins[1] * scale * xres); 96- bmargin = (uint32_t)(crop->margins[2] * scale * yres); 97- rmargin = (uint32_t)(crop->margins[3] * scale * xres); 98+ tmargin = _TIFFClampDoubleToUInt32(crop->margins[0] * scale * yres); 99+ lmargin = _TIFFClampDoubleToUInt32(crop->margins[1] * scale * xres); 100+ bmargin = _TIFFClampDoubleToUInt32(crop->margins[2] * scale * yres); 101+ rmargin = _TIFFClampDoubleToUInt32(crop->margins[3] * scale * xres); 102 } 103 104 if ((lmargin + rmargin) > image->width) 105@@ -5295,24 +5295,24 @@ computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image, 106 if (crop->res_unit != RESUNIT_INCH && crop->res_unit != RESUNIT_CENTIMETER) 107 { 108 if (crop->crop_mode & CROP_WIDTH) 109- width = (uint32_t)crop->width; 110+ width = _TIFFClampDoubleToUInt32(crop->width); 111 else 112 width = image->width - lmargin - rmargin; 113 114 if (crop->crop_mode & CROP_LENGTH) 115- length = (uint32_t)crop->length; 116+ length = _TIFFClampDoubleToUInt32(crop->length); 117 else 118 length = image->length - tmargin - bmargin; 119 } 120 else 121 { 122 if (crop->crop_mode & CROP_WIDTH) 123- width = (uint32_t)(crop->width * scale * image->xres); 124+ width = _TIFFClampDoubleToUInt32(crop->width * scale * image->xres); 125 else 126 width = image->width - lmargin - rmargin; 127 128 if (crop->crop_mode & CROP_LENGTH) 129- length = (uint32_t)(crop->length * scale * image->yres); 130+ length = _TIFFClampDoubleToUInt32(crop->length * scale * image->yres); 131 else 132 length = image->length - tmargin - bmargin; 133 } 134@@ -5711,13 +5711,13 @@ computeOutputPixelOffsets (struct crop_mask *crop, struct image_data *image, 135 { 136 if (page->res_unit == RESUNIT_INCH || page->res_unit == RESUNIT_CENTIMETER) 137 { /* inches or centimeters specified */ 138- hmargin = (uint32_t)(page->hmargin * scale * page->hres * ((image->bps + 7) / 8)); 139- vmargin = (uint32_t)(page->vmargin * scale * page->vres * ((image->bps + 7) / 8)); 140+ hmargin = _TIFFClampDoubleToUInt32(page->hmargin * scale * page->hres * ((image->bps + 7) / 8)); 141+ vmargin = _TIFFClampDoubleToUInt32(page->vmargin * scale * page->vres * ((image->bps + 7) / 8)); 142 } 143 else 144 { /* Otherwise user has specified pixels as reference unit */ 145- hmargin = (uint32_t)(page->hmargin * scale * ((image->bps + 7) / 8)); 146- vmargin = (uint32_t)(page->vmargin * scale * ((image->bps + 7) / 8)); 147+ hmargin = _TIFFClampDoubleToUInt32(page->hmargin * scale * ((image->bps + 7) / 8)); 148+ vmargin = _TIFFClampDoubleToUInt32(page->vmargin * scale * ((image->bps + 7) / 8)); 149 } 150 151 if ((hmargin * 2.0) > (pwidth * page->hres)) 152@@ -5755,13 +5755,13 @@ computeOutputPixelOffsets (struct crop_mask *crop, struct image_data *image, 153 { 154 if (page->mode & PAGE_MODE_PAPERSIZE ) 155 { 156- owidth = (uint32_t)((pwidth * page->hres) - (hmargin * 2)); 157- olength = (uint32_t)((plength * page->vres) - (vmargin * 2)); 158+ owidth = _TIFFClampDoubleToUInt32((pwidth * page->hres) - (hmargin * 2)); 159+ olength = _TIFFClampDoubleToUInt32((plength * page->vres) - (vmargin * 2)); 160 } 161 else 162 { 163- owidth = (uint32_t)(iwidth - (hmargin * 2 * page->hres)); 164- olength = (uint32_t)(ilength - (vmargin * 2 * page->vres)); 165+ owidth = _TIFFClampDoubleToUInt32(iwidth - (hmargin * 2 * page->hres)); 166+ olength = _TIFFClampDoubleToUInt32(ilength - (vmargin * 2 * page->vres)); 167 } 168 } 169 170@@ -5770,6 +5770,12 @@ computeOutputPixelOffsets (struct crop_mask *crop, struct image_data *image, 171 if (olength > ilength) 172 olength = ilength; 173 174+ if (owidth == 0 || olength == 0) 175+ { 176+ TIFFError("computeOutputPixelOffsets", "Integer overflow when calculating the number of pages"); 177+ exit(EXIT_FAILURE); 178+ } 179+ 180 /* Compute the number of pages required for Portrait or Landscape */ 181 switch (page->orient) 182 { 183