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