* libtiff/tif_dirread.c: TIFFFetchStripThing(): limit the number of items
read in StripOffsets/StripByteCounts tags to the number of strips to avoid excessive memory allocation. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2215 Credit to OSS Fuzz
This commit is contained in:
parent
56d802d409
commit
7057734d98
@ -1,3 +1,11 @@
|
|||||||
|
2017-06-12 Even Rouault <even.rouault at spatialys.com>
|
||||||
|
|
||||||
|
* libtiff/tif_dirread.c: TIFFFetchStripThing(): limit the number of items
|
||||||
|
read in StripOffsets/StripByteCounts tags to the number of strips to avoid
|
||||||
|
excessive memory allocation.
|
||||||
|
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2215
|
||||||
|
Credit to OSS Fuzz
|
||||||
|
|
||||||
2017-06-12 Even Rouault <even.rouault at spatialys.com>
|
2017-06-12 Even Rouault <even.rouault at spatialys.com>
|
||||||
|
|
||||||
* libtiff/tif_dirread.c: fix regression of libtiff 4.0.8 in
|
* libtiff/tif_dirread.c: fix regression of libtiff 4.0.8 in
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tif_dirread.c,v 1.210 2017-06-12 10:45:35 erouault Exp $ */
|
/* $Id: tif_dirread.c,v 1.211 2017-06-12 19:13:49 erouault Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988-1997 Sam Leffler
|
* Copyright (c) 1988-1997 Sam Leffler
|
||||||
@ -765,13 +765,20 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* di
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, void** value)
|
static enum TIFFReadDirEntryErr TIFFReadDirEntryArrayWithLimit(
|
||||||
|
TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize,
|
||||||
|
void** value, uint64 maxcount)
|
||||||
{
|
{
|
||||||
int typesize;
|
int typesize;
|
||||||
uint32 datasize;
|
uint32 datasize;
|
||||||
void* data;
|
void* data;
|
||||||
|
uint64 target_count64;
|
||||||
typesize=TIFFDataWidth(direntry->tdir_type);
|
typesize=TIFFDataWidth(direntry->tdir_type);
|
||||||
if ((direntry->tdir_count==0)||(typesize==0))
|
|
||||||
|
target_count64 = (direntry->tdir_count > maxcount) ?
|
||||||
|
maxcount : direntry->tdir_count;
|
||||||
|
|
||||||
|
if ((target_count64==0)||(typesize==0))
|
||||||
{
|
{
|
||||||
*value=0;
|
*value=0;
|
||||||
return(TIFFReadDirEntryErrOk);
|
return(TIFFReadDirEntryErrOk);
|
||||||
@ -783,12 +790,12 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* d
|
|||||||
* in either the current data type or the dest data type. This also
|
* in either the current data type or the dest data type. This also
|
||||||
* avoids problems with overflow of tmsize_t on 32bit systems.
|
* avoids problems with overflow of tmsize_t on 32bit systems.
|
||||||
*/
|
*/
|
||||||
if ((uint64)(2147483647/typesize)<direntry->tdir_count)
|
if ((uint64)(2147483647/typesize)<target_count64)
|
||||||
return(TIFFReadDirEntryErrSizesan);
|
return(TIFFReadDirEntryErrSizesan);
|
||||||
if ((uint64)(2147483647/desttypesize)<direntry->tdir_count)
|
if ((uint64)(2147483647/desttypesize)<target_count64)
|
||||||
return(TIFFReadDirEntryErrSizesan);
|
return(TIFFReadDirEntryErrSizesan);
|
||||||
|
|
||||||
*count=(uint32)direntry->tdir_count;
|
*count=(uint32)target_count64;
|
||||||
datasize=(*count)*typesize;
|
datasize=(*count)*typesize;
|
||||||
assert((tmsize_t)datasize>0);
|
assert((tmsize_t)datasize>0);
|
||||||
data=_TIFFCheckMalloc(tif, *count, typesize, "ReadDirEntryArray");
|
data=_TIFFCheckMalloc(tif, *count, typesize, "ReadDirEntryArray");
|
||||||
@ -834,6 +841,12 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* d
|
|||||||
return(TIFFReadDirEntryErrOk);
|
return(TIFFReadDirEntryErrOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, void** value)
|
||||||
|
{
|
||||||
|
return TIFFReadDirEntryArrayWithLimit(tif, direntry, count,
|
||||||
|
desttypesize, value, ~((uint64)0));
|
||||||
|
}
|
||||||
|
|
||||||
static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray(TIFF* tif, TIFFDirEntry* direntry, uint8** value)
|
static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray(TIFF* tif, TIFFDirEntry* direntry, uint8** value)
|
||||||
{
|
{
|
||||||
enum TIFFReadDirEntryErr err;
|
enum TIFFReadDirEntryErr err;
|
||||||
@ -1863,7 +1876,8 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntrySlongArray(TIFF* tif, TIFFDirEnt
|
|||||||
return(TIFFReadDirEntryErrOk);
|
return(TIFFReadDirEntryErrOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value)
|
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8ArrayWithLimit(
|
||||||
|
TIFF* tif, TIFFDirEntry* direntry, uint64** value, uint64 maxcount)
|
||||||
{
|
{
|
||||||
enum TIFFReadDirEntryErr err;
|
enum TIFFReadDirEntryErr err;
|
||||||
uint32 count;
|
uint32 count;
|
||||||
@ -1883,7 +1897,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEnt
|
|||||||
default:
|
default:
|
||||||
return(TIFFReadDirEntryErrType);
|
return(TIFFReadDirEntryErrType);
|
||||||
}
|
}
|
||||||
err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata);
|
err=TIFFReadDirEntryArrayWithLimit(tif,direntry,&count,8,&origdata,maxcount);
|
||||||
if ((err!=TIFFReadDirEntryErrOk)||(origdata==0))
|
if ((err!=TIFFReadDirEntryErrOk)||(origdata==0))
|
||||||
{
|
{
|
||||||
*value=0;
|
*value=0;
|
||||||
@ -2029,6 +2043,11 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEnt
|
|||||||
return(TIFFReadDirEntryErrOk);
|
return(TIFFReadDirEntryErrOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value)
|
||||||
|
{
|
||||||
|
return TIFFReadDirEntryLong8ArrayWithLimit(tif, direntry, value, ~((uint64)0));
|
||||||
|
}
|
||||||
|
|
||||||
static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array(TIFF* tif, TIFFDirEntry* direntry, int64** value)
|
static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array(TIFF* tif, TIFFDirEntry* direntry, int64** value)
|
||||||
{
|
{
|
||||||
enum TIFFReadDirEntryErr err;
|
enum TIFFReadDirEntryErr err;
|
||||||
@ -3989,6 +4008,7 @@ TIFFReadDirectory(TIFF* tif)
|
|||||||
tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) )
|
tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) )
|
||||||
|
|
||||||
} else if (tif->tif_dir.td_nstrips == 1
|
} else if (tif->tif_dir.td_nstrips == 1
|
||||||
|
&& !(tif->tif_flags&TIFF_ISTILED)
|
||||||
&& _TIFFFillStriles(tif)
|
&& _TIFFFillStriles(tif)
|
||||||
&& tif->tif_dir.td_stripoffset[0] != 0
|
&& tif->tif_dir.td_stripoffset[0] != 0
|
||||||
&& BYTECOUNTLOOKSBAD) {
|
&& BYTECOUNTLOOKSBAD) {
|
||||||
@ -5433,14 +5453,14 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp)
|
|||||||
static const char module[] = "TIFFFetchStripThing";
|
static const char module[] = "TIFFFetchStripThing";
|
||||||
enum TIFFReadDirEntryErr err;
|
enum TIFFReadDirEntryErr err;
|
||||||
uint64* data;
|
uint64* data;
|
||||||
err=TIFFReadDirEntryLong8Array(tif,dir,&data);
|
err=TIFFReadDirEntryLong8ArrayWithLimit(tif,dir,&data,nstrips);
|
||||||
if (err!=TIFFReadDirEntryErrOk)
|
if (err!=TIFFReadDirEntryErrOk)
|
||||||
{
|
{
|
||||||
const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag);
|
const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag);
|
||||||
TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
|
TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
if (dir->tdir_count!=(uint64)nstrips)
|
if (dir->tdir_count<(uint64)nstrips)
|
||||||
{
|
{
|
||||||
uint64* resizeddata;
|
uint64* resizeddata;
|
||||||
resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array");
|
resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array");
|
||||||
@ -5448,13 +5468,8 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp)
|
|||||||
_TIFFfree(data);
|
_TIFFfree(data);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
if (dir->tdir_count<(uint64)nstrips)
|
|
||||||
{
|
|
||||||
_TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64));
|
_TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64));
|
||||||
_TIFFmemset(resizeddata+(uint32)dir->tdir_count,0,(nstrips-(uint32)dir->tdir_count)*sizeof(uint64));
|
_TIFFmemset(resizeddata+(uint32)dir->tdir_count,0,(nstrips-(uint32)dir->tdir_count)*sizeof(uint64));
|
||||||
}
|
|
||||||
else
|
|
||||||
_TIFFmemcpy(resizeddata,data,nstrips*sizeof(uint64));
|
|
||||||
_TIFFfree(data);
|
_TIFFfree(data);
|
||||||
data=resizeddata;
|
data=resizeddata;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user