Index: freeimage/Source/FreeImage/PluginTIFF.cpp
===================================================================
@@ -122,9 +122,14 @@ static void ReadThumbnail(FreeImageIO *i
static int s_format_id;
typedef struct {
+ //! FreeImage IO functions
FreeImageIO *io;
+ //! FreeImage handle
fi_handle handle;
+ //! LibTIFF handle
TIFF *tif;
+ //! Count the number of thumbnails already read (used to avoid recursion on loading)
+ unsigned thumbnailCount;
} fi_TIFFIO;
// ----------------------------------------------------------
@@ -184,10 +189,8 @@ Open a TIFF file descriptor for reading
*/
TIFF *
TIFFFdOpen(thandle_t handle, const char *name, const char *mode) {
- TIFF *tif;
-
// Open the file; the callback will set everything up
- tif = TIFFClientOpen(name, mode, handle,
+ TIFF *tif = TIFFClientOpen(name, mode, handle,
_tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
_tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
@@ -460,9 +463,9 @@ CreateImageType(BOOL header_only, FREE_I
}
}
- else {
+ else if (bpp <= 32) {
- dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
}
@@ -1053,6 +1056,7 @@ Open(FreeImageIO *io, fi_handle handle,
if(!fio) return NULL;
fio->io = io;
fio->handle = handle;
+ fio->thumbnailCount = 0;
if (read) {
fio->tif = TIFFFdOpen((thandle_t)fio, "", "r");
@@ -1108,6 +1112,27 @@ check for uncommon bitspersample values
*/
static BOOL
IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) {
+ // get the pixel depth in bits
+ const uint16 pixel_depth = bitspersample * samplesperpixel;
+
+ // check for a supported pixel depth
+ switch (pixel_depth) {
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ case 48:
+ case 64:
+ case 96:
+ case 128:
+ // OK, go on
+ break;
+ default:
+ // unsupported pixel depth
+ return FALSE;
+ }
switch(bitspersample) {
case 1:
@@ -1148,6 +1173,8 @@ IsValidBitsPerSample(uint16 photometric,
default:
return FALSE;
}
+
+ return FALSE;
}
static TIFFLoadMethod
@@ -1237,16 +1264,32 @@ Read embedded thumbnail
static void
ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) {
FIBITMAP* thumbnail = NULL;
+
+ fi_TIFFIO *fio = (fi_TIFFIO*)data;
+
+ /*
+ Thumbnail loading can cause recursions because of the way
+ functions TIFFLastDirectory and TIFFSetSubDirectory are working.
+ We use here a hack to count the number of times the ReadThumbnail function was called.
+ We only allow one call, check for this
+ */
+ if (fio->thumbnailCount > 0) {
+ return;
+ }
+ else {
+ // update the thumbnail count (used to avoid recursion)
+ fio->thumbnailCount++;
+ }
// read exif thumbnail (IFD 1) ...
- /*
- // this code can cause unwanted recursion causing an overflow, it is thus disabled until we have a better solution
- // do we really need to read a thumbnail from the Exif segment ? knowing that TIFF store the thumbnail in the subIFD ...
- //
toff_t exif_offset = 0;
if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) {
+ // this code can cause unwanted recursion causing an overflow,
+ // because of the way TIFFLastDirectory work => this is checked
+ // using
+
if(!TIFFLastDirectory(tiff)) {
// save current position
const long tell_pos = io->tell_proc(handle);
@@ -1264,7 +1307,6 @@ ReadThumbnail(FreeImageIO *io, fi_handle
TIFFSetDirectory(tiff, cur_dir);
}
}
- */
// ... or read the first subIFD
@@ -1281,6 +1323,10 @@ ReadThumbnail(FreeImageIO *io, fi_handle
const long tell_pos = io->tell_proc(handle);
const uint16 cur_dir = TIFFCurrentDirectory(tiff);
+ // this code can cause unwanted recursion
+ // causing an overflow, because of the way
+ // TIFFSetSubDirectory work
+
if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) {
// load the thumbnail
int page = -1;
@@ -2041,7 +2087,7 @@ Load(FreeImageIO *io, fi_handle handle,
}
// calculate src line and dst pitch
- int dst_pitch = FreeImage_GetPitch(dib);
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
uint32 tileRowSize = (uint32)TIFFTileRowSize(tif);
uint32 imageRowSize = (uint32)TIFFScanlineSize(tif);
@@ -2071,7 +2117,7 @@ Load(FreeImageIO *io, fi_handle handle,
BYTE *src_bits = tileBuffer;
BYTE *dst_bits = bits + rowSize;
for(int k = 0; k < nrows; k++) {
- memcpy(dst_bits, src_bits, src_line);
+ memcpy(dst_bits, src_bits, MIN(dst_pitch, src_line));
src_bits += tileRowSize;
dst_bits -= dst_pitch;
}