|
| 1 | +Index: freeimage/Source/FreeImage/PluginTIFF.cpp |
| 2 | +=================================================================== |
| 3 | +--- freeimage.orig/Source/FreeImage/PluginTIFF.cpp |
| 4 | ++++ freeimage/Source/FreeImage/PluginTIFF.cpp |
| 5 | +@@ -122,9 +122,14 @@ static void ReadThumbnail(FreeImageIO *i |
| 6 | + static int s_format_id; |
| 7 | + |
| 8 | + typedef struct { |
| 9 | ++ //! FreeImage IO functions |
| 10 | + FreeImageIO *io; |
| 11 | ++ //! FreeImage handle |
| 12 | + fi_handle handle; |
| 13 | ++ //! LibTIFF handle |
| 14 | + TIFF *tif; |
| 15 | ++ //! Count the number of thumbnails already read (used to avoid recursion on loading) |
| 16 | ++ unsigned thumbnailCount; |
| 17 | + } fi_TIFFIO; |
| 18 | + |
| 19 | + // ---------------------------------------------------------- |
| 20 | +@@ -184,10 +189,8 @@ Open a TIFF file descriptor for reading |
| 21 | + */ |
| 22 | + TIFF * |
| 23 | + TIFFFdOpen(thandle_t handle, const char *name, const char *mode) { |
| 24 | +- TIFF *tif; |
| 25 | +- |
| 26 | + // Open the file; the callback will set everything up |
| 27 | +- tif = TIFFClientOpen(name, mode, handle, |
| 28 | ++ TIFF *tif = TIFFClientOpen(name, mode, handle, |
| 29 | + _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, |
| 30 | + _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); |
| 31 | + |
| 32 | +@@ -460,9 +463,9 @@ CreateImageType(BOOL header_only, FREE_I |
| 33 | + } |
| 34 | + |
| 35 | + } |
| 36 | +- else { |
| 37 | ++ else if (bpp <= 32) { |
| 38 | + |
| 39 | +- dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); |
| 40 | ++ dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); |
| 41 | + } |
| 42 | + |
| 43 | + |
| 44 | +@@ -1053,6 +1056,7 @@ Open(FreeImageIO *io, fi_handle handle, |
| 45 | + if(!fio) return NULL; |
| 46 | + fio->io = io; |
| 47 | + fio->handle = handle; |
| 48 | ++ fio->thumbnailCount = 0; |
| 49 | + |
| 50 | + if (read) { |
| 51 | + fio->tif = TIFFFdOpen((thandle_t)fio, "", "r"); |
| 52 | +@@ -1108,6 +1112,27 @@ check for uncommon bitspersample values |
| 53 | + */ |
| 54 | + static BOOL |
| 55 | + IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) { |
| 56 | ++ // get the pixel depth in bits |
| 57 | ++ const uint16 pixel_depth = bitspersample * samplesperpixel; |
| 58 | ++ |
| 59 | ++ // check for a supported pixel depth |
| 60 | ++ switch (pixel_depth) { |
| 61 | ++ case 1: |
| 62 | ++ case 4: |
| 63 | ++ case 8: |
| 64 | ++ case 16: |
| 65 | ++ case 24: |
| 66 | ++ case 32: |
| 67 | ++ case 48: |
| 68 | ++ case 64: |
| 69 | ++ case 96: |
| 70 | ++ case 128: |
| 71 | ++ // OK, go on |
| 72 | ++ break; |
| 73 | ++ default: |
| 74 | ++ // unsupported pixel depth |
| 75 | ++ return FALSE; |
| 76 | ++ } |
| 77 | + |
| 78 | + switch(bitspersample) { |
| 79 | + case 1: |
| 80 | +@@ -1148,6 +1173,8 @@ IsValidBitsPerSample(uint16 photometric, |
| 81 | + default: |
| 82 | + return FALSE; |
| 83 | + } |
| 84 | ++ |
| 85 | ++ return FALSE; |
| 86 | + } |
| 87 | + |
| 88 | + static TIFFLoadMethod |
| 89 | +@@ -1237,16 +1264,32 @@ Read embedded thumbnail |
| 90 | + static void |
| 91 | + ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) { |
| 92 | + FIBITMAP* thumbnail = NULL; |
| 93 | ++ |
| 94 | ++ fi_TIFFIO *fio = (fi_TIFFIO*)data; |
| 95 | ++ |
| 96 | ++ /* |
| 97 | ++ Thumbnail loading can cause recursions because of the way |
| 98 | ++ functions TIFFLastDirectory and TIFFSetSubDirectory are working. |
| 99 | ++ We use here a hack to count the number of times the ReadThumbnail function was called. |
| 100 | ++ We only allow one call, check for this |
| 101 | ++ */ |
| 102 | ++ if (fio->thumbnailCount > 0) { |
| 103 | ++ return; |
| 104 | ++ } |
| 105 | ++ else { |
| 106 | ++ // update the thumbnail count (used to avoid recursion) |
| 107 | ++ fio->thumbnailCount++; |
| 108 | ++ } |
| 109 | + |
| 110 | + // read exif thumbnail (IFD 1) ... |
| 111 | + |
| 112 | +- /* |
| 113 | +- // this code can cause unwanted recursion causing an overflow, it is thus disabled until we have a better solution |
| 114 | +- // do we really need to read a thumbnail from the Exif segment ? knowing that TIFF store the thumbnail in the subIFD ... |
| 115 | +- // |
| 116 | + toff_t exif_offset = 0; |
| 117 | + if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { |
| 118 | + |
| 119 | ++ // this code can cause unwanted recursion causing an overflow, |
| 120 | ++ // because of the way TIFFLastDirectory work => this is checked |
| 121 | ++ // using |
| 122 | ++ |
| 123 | + if(!TIFFLastDirectory(tiff)) { |
| 124 | + // save current position |
| 125 | + const long tell_pos = io->tell_proc(handle); |
| 126 | +@@ -1264,7 +1307,6 @@ ReadThumbnail(FreeImageIO *io, fi_handle |
| 127 | + TIFFSetDirectory(tiff, cur_dir); |
| 128 | + } |
| 129 | + } |
| 130 | +- */ |
| 131 | + |
| 132 | + // ... or read the first subIFD |
| 133 | + |
| 134 | +@@ -1281,6 +1323,10 @@ ReadThumbnail(FreeImageIO *io, fi_handle |
| 135 | + const long tell_pos = io->tell_proc(handle); |
| 136 | + const uint16 cur_dir = TIFFCurrentDirectory(tiff); |
| 137 | + |
| 138 | ++ // this code can cause unwanted recursion |
| 139 | ++ // causing an overflow, because of the way |
| 140 | ++ // TIFFSetSubDirectory work |
| 141 | ++ |
| 142 | + if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) { |
| 143 | + // load the thumbnail |
| 144 | + int page = -1; |
| 145 | +@@ -2041,7 +2087,7 @@ Load(FreeImageIO *io, fi_handle handle, |
| 146 | + } |
| 147 | + |
| 148 | + // calculate src line and dst pitch |
| 149 | +- int dst_pitch = FreeImage_GetPitch(dib); |
| 150 | ++ unsigned dst_pitch = FreeImage_GetPitch(dib); |
| 151 | + uint32 tileRowSize = (uint32)TIFFTileRowSize(tif); |
| 152 | + uint32 imageRowSize = (uint32)TIFFScanlineSize(tif); |
| 153 | + |
| 154 | +@@ -2071,7 +2117,7 @@ Load(FreeImageIO *io, fi_handle handle, |
| 155 | + BYTE *src_bits = tileBuffer; |
| 156 | + BYTE *dst_bits = bits + rowSize; |
| 157 | + for(int k = 0; k < nrows; k++) { |
| 158 | +- memcpy(dst_bits, src_bits, src_line); |
| 159 | ++ memcpy(dst_bits, src_bits, MIN(dst_pitch, src_line)); |
| 160 | + src_bits += tileRowSize; |
| 161 | + dst_bits -= dst_pitch; |
| 162 | + } |
0 commit comments