r17066 by jghali - #10415 : crash when loading a multipage TIFF into an image frame

scribus-commit scribus-commit at lists.scribus.net
Sat Dec 10 16:40:46 UTC 2011


Author: jghali
Date: Sat Dec 10 16:40:46 2011
New Revision: 17066

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=17066
Log:
#10415 : crash when loading a multipage TIFF into an image frame

Modified:
    trunk/Scribus/scribus/scimgdataloader_tiff.cpp

Modified: trunk/Scribus/scribus/scimgdataloader_tiff.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=17066&path=/trunk/Scribus/scribus/scimgdataloader_tiff.cpp
==============================================================================
--- trunk/Scribus/scribus/scimgdataloader_tiff.cpp (original)
+++ trunk/Scribus/scribus/scimgdataloader_tiff.cpp Sat Dec 10 16:40:46 2011
@@ -110,7 +110,7 @@
 	struct PSDLayer lay;
 	TIFFSetTagExtender(TagExtender);
 	TIFF* tif = TIFFOpen(fn.toLocal8Bit(), "r");
-	if(tif)
+	if (tif)
 	{
 		do
 		{
@@ -304,7 +304,7 @@
 {
 	bool gotData = false;
 	uint32* bits = (uint32 *) _TIFFmalloc(size * sizeof(uint32));
-	uint16  extrasamples, *extratypes;
+	uint16  extrasamples(0), *extratypes(0);
 	if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &extratypes))
 		extrasamples = 0;
 	if(bits)
@@ -622,7 +622,6 @@
 		random_table[swap] = tmp;
 	}
 	int test;
-	int layerNum = 0;
 	bool valid = m_imageInfoRecord.isRequest;
 	QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
 	initialize();
@@ -632,7 +631,7 @@
 	getLayers(fn, page);
 	TIFFSetTagExtender(TagExtender);
 	TIFF* tif = TIFFOpen(fn.toLocal8Bit(), "r");
-	if(tif)
+	if (tif)
 	{
 		bool isCMYK = false;
 		unsigned int widtht, heightt, size;
@@ -985,7 +984,7 @@
 				return false;
 			}
 			r_image.fill(0);
-			bool firstL = true;
+			int layerNum = 0;
 			do
 			{
 				RawImage tmpImg;
@@ -994,58 +993,67 @@
 					TIFFClose(tif);
 					return false;
 				}
+
+				tmpImg.fill(0);
+				if (!getImageData(tif, &tmpImg, widtht, heightt, size, photometric, bitspersample, samplesperpixel, bilevel, isCMYK))
+				{
+					TIFFClose(tif);
+					return false;
+				}
+				bool visible = true;
+				bool useMask = true;
+				if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
+					visible = m_imageInfoRecord.RequestProps[layerNum].visible;
+				QString layBlend = "norm";
+				if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
+					layBlend = m_imageInfoRecord.RequestProps[layerNum].blend;
+				if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
+					useMask = m_imageInfoRecord.RequestProps[layerNum].useMask;
+				int layOpa = 255;
+				if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
+					layOpa = m_imageInfoRecord.RequestProps[layerNum].opacity;
+				if (visible)
+				{
+					if ((layerNum == 0) && (layBlend != "diss"))
+						r_image = tmpImg;
+					else
+						blendOntoTarget(&tmpImg, layOpa, layBlend, isCMYK, useMask);
+				}
+				//JG Copy should not be necessary as QImage is implicitly shared in Qt4
+				QImage imt; //QImage imt = tmpImg.copy();
+				double sx = tmpImg.width() / 40.0;
+				double sy = tmpImg.height() / 40.0;
+				imt = tmpImg.convertToQImage((chans > 4) ? true : false);
+				imt = sy < sx ?	imt.scaled(qRound(imt.width() / sx), qRound(imt.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) :
+											imt.scaled(qRound(imt.width() / sy), qRound(imt.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+				m_imageInfoRecord.layerInfo[layerNum].thumb = imt.copy();
+				if (chans > 4)
+				{
+					QImage imt2 = imt.createAlphaMask();
+					imt2.invertPixels();
+					m_imageInfoRecord.layerInfo[layerNum].thumb_mask = imt2.copy();
+				}
 				else
-				{
-					tmpImg.fill(0);
-					if (!getImageData(tif, &tmpImg, widtht, heightt, size, photometric, bitspersample, samplesperpixel, bilevel, isCMYK))
-					{
-						TIFFClose(tif);
-						return false;
-					}
-					bool visible = true;
-					bool useMask = true;
-					if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
-						visible = m_imageInfoRecord.RequestProps[layerNum].visible;
-					QString layBlend = "norm";
-					if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
-						layBlend = m_imageInfoRecord.RequestProps[layerNum].blend;
-					if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
-						useMask = m_imageInfoRecord.RequestProps[layerNum].useMask;
-					int layOpa = 255;
-					if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum)))
-						layOpa = m_imageInfoRecord.RequestProps[layerNum].opacity;
-					if (visible)
-					{
-						if ((firstL) && (layBlend != "diss"))
-							r_image = tmpImg;
-						else
-							blendOntoTarget(&tmpImg, layOpa, layBlend, isCMYK, useMask);
-						firstL = false;
-					}
-					//JG Copy should not be necessary as QImage is implicitly shared in Qt4
-					QImage imt; //QImage imt = tmpImg.copy();
-					if (chans > 4)
-						imt = tmpImg.convertToQImage(true);
-					else
-						imt = tmpImg.convertToQImage(false);
-					double sx = tmpImg.width() / 40.0;
-					double sy = tmpImg.height() / 40.0;
-					imt = sy < sx ?	imt.scaled(qRound(imt.width() / sx), qRound(imt.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) :
-												imt.scaled(qRound(imt.width() / sy), qRound(imt.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-					m_imageInfoRecord.layerInfo[layerNum].thumb = imt.copy();
-					if (chans > 4)
-					{
-						QImage imt2 = imt.createAlphaMask();
-						imt2.invertPixels();
-						m_imageInfoRecord.layerInfo[layerNum].thumb_mask = imt2.copy();
-					}
-					else
-						m_imageInfoRecord.layerInfo[layerNum].thumb_mask = QImage();
-					layerNum++;
-				}
+					m_imageInfoRecord.layerInfo[layerNum].thumb_mask = QImage();
+				layerNum++;
+
 				if ((m_imageInfoRecord.layerInfo.count() == 1) && (chans < 5))
 					m_imageInfoRecord.layerInfo.clear();
 				test = TIFFReadDirectory(tif);
+
+				// #10415 : check that image size for the current directory is the same as the main one
+				// Some progs use tiff directory to store previews, we do not handle such case
+				// and may perform reads in non allocated blocks if we continue
+				while (test == 1)
+				{
+					unsigned int dirWidth(0), dirHeight(0);
+					TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &dirWidth);
+					TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &dirHeight);
+					if (dirWidth == widtht && dirHeight == heightt)
+						break;
+					test = TIFFReadDirectory(tif);
+					layerNum++;
+				}
 			}
 			while (test == 1);
 			TIFFClose(tif);




More information about the scribus-commit mailing list