|
@@ -0,0 +1,188 @@
|
|
|
|
|
+CVE: CVE-2019-12211
|
|
|
|
|
+CVE: CVE-2019-12213
|
|
|
|
|
+Upstream: https://src.fedoraproject.org/rpms/freeimage/raw/78980acf39f02b88e70f27e37e5a191c9a9ead47/f/CVE-2019-12211_2019-12213.patch
|
|
|
|
|
+Signed-off-by: Thomas Perale <thomas.perale@mind.be>
|
|
|
|
|
+---
|
|
|
|
|
+diff -rupN a/Source/FreeImage/PluginTIFF.cpp b/Source/FreeImage/PluginTIFF.cpp
|
|
|
|
|
+--- a/Source/FreeImage/PluginTIFF.cpp
|
|
|
|
|
++++ b/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,12 +463,10 @@ CreateImageType(BOOL header_only, FREE_I
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+- else {
|
|
|
|
|
+-
|
|
|
|
|
+- dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
|
|
|
|
|
++ else if (bpp <= 32) {
|
|
|
|
|
++ dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+-
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // other bitmap types
|
|
|
|
|
+
|
|
|
|
|
+@@ -1050,9 +1051,12 @@ static void * DLL_CALLCONV
|
|
|
|
|
+ Open(FreeImageIO *io, fi_handle handle, BOOL read) {
|
|
|
|
|
+ // wrapper for TIFF I/O
|
|
|
|
|
+ fi_TIFFIO *fio = (fi_TIFFIO*)malloc(sizeof(fi_TIFFIO));
|
|
|
|
|
+- if(!fio) return NULL;
|
|
|
|
|
++ 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,15 +1264,30 @@ 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
|
|
|
|
|
+@@ -1256,15 +1298,15 @@ ReadThumbnail(FreeImageIO *io, fi_handle
|
|
|
|
|
+ int page = 1;
|
|
|
|
|
+ int flags = TIFF_DEFAULT;
|
|
|
|
|
+ thumbnail = Load(io, handle, page, flags, data);
|
|
|
|
|
++
|
|
|
|
|
+ // store the thumbnail (remember to release it before return)
|
|
|
|
|
+ FreeImage_SetThumbnail(dib, thumbnail);
|
|
|
|
|
+-
|
|
|
|
|
++
|
|
|
|
|
+ // restore current position
|
|
|
|
|
+ io->seek_proc(handle, tell_pos, SEEK_SET);
|
|
|
|
|
+ TIFFSetDirectory(tiff, cur_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+- */
|
|
|
|
|
+
|
|
|
|
|
+ // ... or read the first subIFD
|
|
|
|
|
+
|
|
|
|
|
+@@ -1281,11 +1323,14 @@ 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;
|
|
|
|
|
+ int flags = TIFF_DEFAULT;
|
|
|
|
|
+ thumbnail = Load(io, handle, page, flags, data);
|
|
|
|
|
++
|
|
|
|
|
+ // store the thumbnail (remember to release it before return)
|
|
|
|
|
+ FreeImage_SetThumbnail(dib, thumbnail);
|
|
|
|
|
+ }
|
|
|
|
|
+@@ -2041,7 +2086,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 +2116,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;
|
|
|
|
|
+ }
|