Fix a number of out-of-bound reads and writes, including CVE-2015-8665 and

CVE-2015-8683.  From upstream CVS.
This commit is contained in:
naddy 2016-01-24 16:48:48 +00:00
parent ca216aae26
commit 7c8440a0fc
4 changed files with 318 additions and 30 deletions

View File

@ -1,8 +1,9 @@
# $OpenBSD: Makefile,v 1.74 2015/11/04 20:51:36 naddy Exp $
# $OpenBSD: Makefile,v 1.75 2016/01/24 16:48:48 naddy Exp $
COMMENT= tools and library routines for working with TIFF images
DISTNAME= tiff-4.0.6
REVISION= 0
SHARED_LIBS= tiff 39.2 # 7.4
SHARED_LIBS+= tiffxx 40.1 # 7.4
CATEGORIES= graphics

View File

@ -1,11 +1,17 @@
$OpenBSD: patch-libtiff_tif_getimage_c,v 1.9 2015/03/29 17:39:22 naddy Exp $
$OpenBSD: patch-libtiff_tif_getimage_c,v 1.10 2016/01/24 16:48:49 naddy Exp $
This one is slightly problematic. If an application allocates less
room for its error buffer than the recommended 1024, the error message
buffer will still overflow.
* libtiff/tif_getimage.c: fix out-of-bound reads in TIFFRGBAImage
interface in case of unsupported values of SamplesPerPixel/ExtraSamples
for LogLUV / CIELab. Add explicit call to TIFFRGBAImageOK() in
TIFFRGBAImageBegin(). Fix CVE-2015-8665 reported by limingxing and
CVE-2015-8683 reported by zzf of Alibaba.
--- libtiff/tif_getimage.c.orig Mon Dec 29 19:28:46 2014
+++ libtiff/tif_getimage.c Sun Mar 29 17:09:38 2015
This snprintf conversion is slightly problematic. If an application
allocates less room for its error buffer than the recommended 1024,
the error message buffer will still overflow.
--- libtiff/tif_getimage.c.orig Sat Aug 29 00:16:22 2015
+++ libtiff/tif_getimage.c Sun Jan 24 17:04:12 2016
@@ -80,7 +80,7 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
int colorchannels;
@ -76,7 +82,7 @@ buffer will still overflow.
"Compression", COMPRESSION_SGILOG);
return (0);
}
@@ -173,18 +173,18 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
@@ -173,35 +173,37 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
case PHOTOMETRIC_LOGLUV:
if (td->td_compression != COMPRESSION_SGILOG &&
td->td_compression != COMPRESSION_SGILOG24) {
@ -91,23 +97,31 @@ buffer will still overflow.
"Planarconfiguration", td->td_planarconfig);
return (0);
}
if( td->td_samplesperpixel != 3 )
- if( td->td_samplesperpixel != 3 )
+ if( td->td_samplesperpixel != 3 || colorchannels != 3 )
{
- sprintf(emsg,
- "Sorry, can not handle image with %s=%d",
- "Samples/pixel", td->td_samplesperpixel);
+ snprintf(emsg, 1024,
"Sorry, can not handle image with %s=%d",
"Samples/pixel", td->td_samplesperpixel);
+ "Sorry, can not handle image with %s=%d, %s=%d",
+ "Samples/pixel", td->td_samplesperpixel,
+ "colorchannels", colorchannels);
return 0;
@@ -193,7 +193,7 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
}
break;
case PHOTOMETRIC_CIELAB:
if( td->td_samplesperpixel != 3 || td->td_bitspersample != 8 )
- if( td->td_samplesperpixel != 3 || td->td_bitspersample != 8 )
+ if( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 )
{
- sprintf(emsg,
- "Sorry, can not handle image with %s=%d and %s=%d",
+ snprintf(emsg, 1024,
"Sorry, can not handle image with %s=%d and %s=%d",
+ "Sorry, can not handle image with %s=%d, %s=%d and %s=%d",
"Samples/pixel", td->td_samplesperpixel,
+ "colorchannels", colorchannels,
"Bits/sample", td->td_bitspersample);
@@ -201,7 +201,7 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
return 0;
}
break;
default:
@ -116,7 +130,17 @@ buffer will still overflow.
photoTag, photometric);
return (0);
}
@@ -275,7 +275,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -255,6 +257,9 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
int colorchannels;
uint16 *red_orig, *green_orig, *blue_orig;
int n_color;
+
+ if( !TIFFRGBAImageOK(tif, emsg) )
+ return 0;
/* Initialize to normal values */
img->row_offset = 0;
@@ -275,7 +280,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
case 16:
break;
default:
@ -125,7 +149,7 @@ buffer will still overflow.
img->bitspersample);
goto fail_return;
}
@@ -325,7 +325,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -325,7 +330,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
img->photometric = PHOTOMETRIC_RGB;
break;
default:
@ -134,7 +158,7 @@ buffer will still overflow.
goto fail_return;
}
}
@@ -333,7 +333,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -333,7 +338,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
case PHOTOMETRIC_PALETTE:
if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
&red_orig, &green_orig, &blue_orig)) {
@ -143,7 +167,7 @@ buffer will still overflow.
goto fail_return;
}
@@ -343,7 +343,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -343,7 +348,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
@ -152,7 +176,7 @@ buffer will still overflow.
goto fail_return;
}
@@ -357,7 +357,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -357,7 +362,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
if (planarconfig == PLANARCONFIG_CONTIG
&& img->samplesperpixel != 1
&& img->bitspersample < 8 ) {
@ -161,7 +185,7 @@ buffer will still overflow.
"Sorry, can not handle contiguous data with %s=%d, "
"and %s=%d and Bits/Sample=%d",
photoTag, img->photometric,
@@ -394,7 +394,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -394,7 +399,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
break;
case PHOTOMETRIC_RGB:
if (colorchannels < 3) {
@ -170,7 +194,7 @@ buffer will still overflow.
"Color channels", colorchannels);
goto fail_return;
}
@@ -404,12 +404,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -404,12 +409,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
uint16 inkset;
TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
if (inkset != INKSET_CMYK) {
@ -185,7 +209,7 @@ buffer will still overflow.
"Samples/pixel", img->samplesperpixel);
goto fail_return;
}
@@ -417,7 +417,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -417,7 +422,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
break;
case PHOTOMETRIC_LOGL:
if (compress != COMPRESSION_SGILOG) {
@ -194,7 +218,7 @@ buffer will still overflow.
"Compression", COMPRESSION_SGILOG);
goto fail_return;
}
@@ -427,12 +427,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -427,12 +432,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
break;
case PHOTOMETRIC_LOGLUV:
if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
@ -209,7 +233,7 @@ buffer will still overflow.
"Planarconfiguration", planarconfig);
return (0);
}
@@ -443,7 +443,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -443,7 +448,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
case PHOTOMETRIC_CIELAB:
break;
default:
@ -218,7 +242,7 @@ buffer will still overflow.
photoTag, img->photometric);
goto fail_return;
}
@@ -461,12 +461,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
@@ -461,12 +466,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int
!(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1);
if (img->isContig) {
if (!PickContigCase(img)) {
@ -233,3 +257,61 @@ buffer will still overflow.
goto fail_return;
}
}
@@ -2508,29 +2513,33 @@ PickContigCase(TIFFRGBAImage* img)
case PHOTOMETRIC_RGB:
switch (img->bitspersample) {
case 8:
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
+ img->samplesperpixel >= 4)
img->put.contig = putRGBAAcontig8bittile;
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
+ img->samplesperpixel >= 4)
{
if (BuildMapUaToAa(img))
img->put.contig = putRGBUAcontig8bittile;
}
- else
+ else if( img->samplesperpixel >= 3 )
img->put.contig = putRGBcontig8bittile;
break;
case 16:
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
+ img->samplesperpixel >=4 )
{
if (BuildMapBitdepth16To8(img))
img->put.contig = putRGBAAcontig16bittile;
}
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
+ img->samplesperpixel >=4 )
{
if (BuildMapBitdepth16To8(img) &&
BuildMapUaToAa(img))
img->put.contig = putRGBUAcontig16bittile;
}
- else
+ else if( img->samplesperpixel >=3 )
{
if (BuildMapBitdepth16To8(img))
img->put.contig = putRGBcontig16bittile;
@@ -2539,7 +2548,7 @@ PickContigCase(TIFFRGBAImage* img)
}
break;
case PHOTOMETRIC_SEPARATED:
- if (buildMap(img)) {
+ if (img->samplesperpixel >=4 && buildMap(img)) {
if (img->bitspersample == 8) {
if (!img->Map)
img->put.contig = putRGBcontig8bitCMYKtile;
@@ -2635,7 +2644,7 @@ PickContigCase(TIFFRGBAImage* img)
}
break;
case PHOTOMETRIC_CIELAB:
- if (buildMap(img)) {
+ if (img->samplesperpixel == 3 && buildMap(img)) {
if (img->bitspersample == 8)
img->put.contig = initCIELabConversion(img);
break;

View File

@ -1,7 +1,170 @@
$OpenBSD: patch-libtiff_tif_luv_c,v 1.5 2015/07/08 19:36:54 naddy Exp $
--- libtiff/tif_luv.c.orig Sun Jun 21 03:09:09 2015
+++ libtiff/tif_luv.c Wed Jul 8 21:08:06 2015
@@ -702,7 +702,7 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, ui
$OpenBSD: patch-libtiff_tif_luv_c,v 1.6 2016/01/24 16:48:49 naddy Exp $
* libtiff/tif_luv.c: fix potential out-of-bound writes in decode
functions in non debug builds by replacing assert()s by regular if
checks (bugzilla #2522).
Fix potential out-of-bound reads in case of short input data.
Avoid rand() warning in library.
--- libtiff/tif_luv.c.orig Sat Aug 29 00:16:22 2015
+++ libtiff/tif_luv.c Sun Jan 24 17:06:27 2016
@@ -202,7 +202,11 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint1
if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
tp = (int16*) op;
else {
- assert(sp->tbuflen >= npixels);
+ if(sp->tbuflen < npixels) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Translation buffer too short");
+ return (0);
+ }
tp = (int16*) sp->tbuf;
}
_TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
@@ -211,9 +215,11 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint1
cc = tif->tif_rawcc;
/* get each byte string */
for (shft = 2*8; (shft -= 8) >= 0; ) {
- for (i = 0; i < npixels && cc > 0; )
+ for (i = 0; i < npixels && cc > 0; ) {
if (*bp >= 128) { /* run */
- rc = *bp++ + (2-128); /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
+ if( cc < 2 )
+ break;
+ rc = *bp++ + (2-128);
b = (int16)(*bp++ << shft);
cc -= 2;
while (rc-- && i < npixels)
@@ -223,6 +229,7 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint1
while (--cc && rc-- && i < npixels)
tp[i++] |= (int16)*bp++ << shft;
}
+ }
if (i != npixels) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module,
@@ -268,13 +275,17 @@ LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uin
if (sp->user_datafmt == SGILOGDATAFMT_RAW)
tp = (uint32 *)op;
else {
- assert(sp->tbuflen >= npixels);
+ if(sp->tbuflen < npixels) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Translation buffer too short");
+ return (0);
+ }
tp = (uint32 *) sp->tbuf;
}
/* copy to array of uint32 */
bp = (unsigned char*) tif->tif_rawcp;
cc = tif->tif_rawcc;
- for (i = 0; i < npixels && cc > 0; i++) {
+ for (i = 0; i < npixels && cc >= 3; i++) {
tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
bp += 3;
cc -= 3;
@@ -325,7 +336,11 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uin
if (sp->user_datafmt == SGILOGDATAFMT_RAW)
tp = (uint32*) op;
else {
- assert(sp->tbuflen >= npixels);
+ if(sp->tbuflen < npixels) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Translation buffer too short");
+ return (0);
+ }
tp = (uint32*) sp->tbuf;
}
_TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
@@ -334,11 +349,13 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uin
cc = tif->tif_rawcc;
/* get each byte string */
for (shft = 4*8; (shft -= 8) >= 0; ) {
- for (i = 0; i < npixels && cc > 0; )
+ for (i = 0; i < npixels && cc > 0; ) {
if (*bp >= 128) { /* run */
+ if( cc < 2 )
+ break;
rc = *bp++ + (2-128);
b = (uint32)*bp++ << shft;
- cc -= 2; /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
+ cc -= 2;
while (rc-- && i < npixels)
tp[i++] |= b;
} else { /* non-run */
@@ -346,6 +363,7 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uin
while (--cc && rc-- && i < npixels)
tp[i++] |= (uint32)*bp++ << shft;
}
+ }
if (i != npixels) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module,
@@ -413,6 +431,7 @@ LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, ui
static int
LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
{
+ static const char module[] = "LogL16Encode";
LogLuvState* sp = EncoderState(tif);
int shft;
tmsize_t i;
@@ -433,7 +452,11 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16
tp = (int16*) bp;
else {
tp = (int16*) sp->tbuf;
- assert(sp->tbuflen >= npixels);
+ if(sp->tbuflen < npixels) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Translation buffer too short");
+ return (0);
+ }
(*sp->tfunc)(sp, bp, npixels);
}
/* compress each byte string */
@@ -506,6 +529,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16
static int
LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
{
+ static const char module[] = "LogLuvEncode24";
LogLuvState* sp = EncoderState(tif);
tmsize_t i;
tmsize_t npixels;
@@ -521,7 +545,11 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint
tp = (uint32*) bp;
else {
tp = (uint32*) sp->tbuf;
- assert(sp->tbuflen >= npixels);
+ if(sp->tbuflen < npixels) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Translation buffer too short");
+ return (0);
+ }
(*sp->tfunc)(sp, bp, npixels);
}
/* write out encoded pixels */
@@ -553,6 +581,7 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint
static int
LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
{
+ static const char module[] = "LogLuvEncode32";
LogLuvState* sp = EncoderState(tif);
int shft;
tmsize_t i;
@@ -574,7 +603,11 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint
tp = (uint32*) bp;
else {
tp = (uint32*) sp->tbuf;
- assert(sp->tbuflen >= npixels);
+ if(sp->tbuflen < npixels) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Translation buffer too short");
+ return (0);
+ }
(*sp->tfunc)(sp, bp, npixels);
}
/* compress each byte string */
@@ -702,7 +735,7 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, ui
#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \
(int)(x) : \

View File

@ -0,0 +1,42 @@
$OpenBSD: patch-libtiff_tif_next_c,v 1.5 2016/01/24 16:48:49 naddy Exp $
* libtiff/tif_next.c: fix potential out-of-bound write in NeXTDecode()
triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif
(bugzilla #2508)
--- libtiff/tif_next.c.orig Sat Aug 29 00:16:22 2015
+++ libtiff/tif_next.c Sun Jan 24 17:06:54 2016
@@ -37,7 +37,7 @@
case 0: op[0] = (unsigned char) ((v) << 6); break; \
case 1: op[0] |= (v) << 4; break; \
case 2: op[0] |= (v) << 2; break; \
- case 3: *op++ |= (v); break; \
+ case 3: *op++ |= (v); op_offset++; break; \
} \
}
@@ -106,6 +106,7 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16
uint32 imagewidth = tif->tif_dir.td_imagewidth;
if( isTiled(tif) )
imagewidth = tif->tif_dir.td_tilewidth;
+ tmsize_t op_offset = 0;
/*
* The scanline is composed of a sequence of constant
@@ -122,10 +123,15 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16
* bounds, potentially resulting in a security
* issue.
*/
- while (n-- > 0 && npixels < imagewidth)
+ while (n-- > 0 && npixels < imagewidth && op_offset < scanline)
SETPIXEL(op, grey);
if (npixels >= imagewidth)
break;
+ if (op_offset >= scanline ) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld",
+ (long) tif->tif_row);
+ return (0);
+ }
if (cc == 0)
goto bad;
n = *bp++, cc--;