From 87e1914b9db503d1083f55d9a2ac8b8997b1139a Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 3 Jul 2016 16:06:07 +0200 Subject: [PATCH] Fix buffer overrun writing uncompressed tiff --- rtengine/imageio.cc | 21 +++++++++------------ rtexif/rtexif.cc | 18 ++++++++++-------- rtexif/rtexif.h | 2 +- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index f8edfdd58..93c650afe 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -1227,22 +1227,17 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) } // buffer for the exif and iptc - int bufferSize = 175535; //TODO: Is it really 165535... or 65535 ? - - if(profileData) { - bufferSize += profileLength; - } - - unsigned char* buffer = new unsigned char[bufferSize]; - unsigned char* iptcdata = NULL; + unsigned int bufferSize; + unsigned char* buffer = nullptr; // buffer will be allocated in createTIFFHeader + unsigned char* iptcdata = nullptr; unsigned int iptclen = 0; if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) { iptc_data_free_buf (iptc, iptcdata); - iptcdata = NULL; + iptcdata = nullptr; } - int size = rtexif::ExifManager::createTIFFHeader (exifRoot, exifChange, width, height, bps, profileData, profileLength, (char*)iptcdata, iptclen, buffer); + int size = rtexif::ExifManager::createTIFFHeader (exifRoot, exifChange, width, height, bps, profileData, profileLength, (char*)iptcdata, iptclen, buffer, bufferSize); if (iptcdata) { iptc_data_free_buf (iptc, iptcdata); @@ -1250,7 +1245,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) // The maximum lenght is strangely not the same than for the JPEG file... // Which maximum length is the good one ? - if (size > 0 && size < bufferSize) { + if (size > 0 && size <= bufferSize) { fwrite (buffer, size, 1, file); } @@ -1277,7 +1272,9 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) } } - delete [] buffer; + if(buffer) { + delete [] buffer; + } if (ferror(file)) { writeOk = false; diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index f61d90c08..f9b2739d7 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -2864,7 +2864,7 @@ int ExifManager::createJPEGMarker (const TagDirectory* root, const rtengine::pro return size + 6; } -int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char* buffer) +int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize) { // write tiff header @@ -2875,13 +2875,6 @@ int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::pro order = root->getOrder (); } - sset2 ((unsigned short)order, buffer + offs, order); - offs += 2; - sset2 (42, buffer + offs, order); - offs += 2; - sset4 (8, buffer + offs, order); - offs += 4; - TagDirectory* cl; if (root) { @@ -2956,6 +2949,15 @@ int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::pro } cl->sort (); + bufferSize = cl->calculateSize() + 8; + buffer = new unsigned char[bufferSize]; // this has to be deleted in caller + sset2 ((unsigned short)order, buffer + offs, order); + offs += 2; + sset2 (42, buffer + offs, order); + offs += 2; + sset4 (8, buffer + offs, order); + offs += 4; + int endOffs = cl->write (8, buffer); // cl->printAll(); diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 471f9fbe3..a8d7088d2 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -318,7 +318,7 @@ public: /// @return The ownership of the return tags is passed to the caller. static std::vector getDefaultTIFFTags (TagDirectory* forthis); static int createJPEGMarker (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, unsigned char* buffer); - static int createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char* buffer); + static int createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize); }; class Interpreter