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