[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a
Maximiliano Curia
maxy at moszumanska.debian.org
Thu Jul 13 17:36:21 UTC 2017
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=59edeff
The following commit has been merged in the master branch:
commit 59edeff2d84c054675f7e95da2ead3790de87a25
Author: Andreas Huggel <ahuggel at gmx.net>
Date: Thu May 13 16:12:12 2004 +0000
Added len argument and boundary checks to various read functions and slightly improved error handling
---
src/exif.cpp | 200 +++++++++++++++++++++++++++++++++++++++++------------------
src/exif.hpp | 24 ++++++-
2 files changed, 159 insertions(+), 65 deletions(-)
diff --git a/src/exif.cpp b/src/exif.cpp
index b8f3521..744a002 100644
--- a/src/exif.cpp
+++ b/src/exif.cpp
@@ -20,14 +20,14 @@
*/
/*
File: exif.cpp
- Version: $Name: $ $Revision: 1.41 $
+ Version: $Name: $ $Revision: 1.42 $
Author(s): Andreas Huggel (ahu) <ahuggel at gmx.net>
History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component
*/
// *****************************************************************************
#include "rcsid.hpp"
-EXIV2_RCSID("@(#) $Name: $ $Revision: 1.41 $ $RCSfile: exif.cpp,v $")
+EXIV2_RCSID("@(#) $Name: $ $Revision: 1.42 $ $RCSfile: exif.cpp,v $")
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@@ -177,6 +177,7 @@ namespace Exiv2 {
memcpy(pImage_, rhs.pImage_, rhs.size_);
tiffHeader_.read(pImage_);
ifd_.read(pImage_ + tiffHeader_.offset(),
+ size_ - tiffHeader_.offset(),
tiffHeader_.byteOrder(), tiffHeader_.offset());
}
}
@@ -189,6 +190,7 @@ namespace Exiv2 {
memcpy(pNewImage, rhs.pImage_, rhs.size_);
tiffHeader_.read(rhs.pImage_);
ifd_.read(pNewImage + tiffHeader_.offset(),
+ rhs.size_ - tiffHeader_.offset(),
tiffHeader_.byteOrder(), tiffHeader_.offset());
}
offset_ = rhs.offset_;
@@ -199,69 +201,92 @@ namespace Exiv2 {
}
int TiffThumbnail::read(const char* buf,
+ long len,
const ExifData& exifData,
ByteOrder byteOrder)
{
- DataBuf img; // temporary buffer Todo: handle larger
- img.alloc(64*1024); // images (which violate the Exif Std)
+ DataBuf img; // temporary buffer
+ img.alloc(len);
memset(img.pData_, 0x0, img.size_);
- long len = 0; // number of bytes in the buffer
+ long buflen = 0; // actual number of bytes needed
+ int rc = 0;
// Copy the TIFF header
TiffHeader tiffHeader(byteOrder);
- len += tiffHeader.copy(img.pData_);
-
- // Create IFD (without Exif and GPS tags) from metadata
+ if (len < tiffHeader.size()) rc = 1;
Ifd ifd1(ifd1);
- addToIfd(ifd1, exifData.begin(), exifData.end(), tiffHeader.byteOrder());
- ifd1.erase(0x8769);
- ifd1.erase(0x8825);
-
- // Do not copy the IFD yet, remember the location and leave a gap
- long ifdOffset = len;
- len += ifd1.size() + ifd1.dataSize();
-
- // Copy thumbnail image data, remember the offsets used
- std::string key = "Thumbnail.RecordingOffset.StripOffsets";
- ExifData::const_iterator offsets = exifData.findKey(key);
- if (offsets == exifData.end()) return 2;
- key = "Thumbnail.RecordingOffset.StripByteCounts";
- ExifData::const_iterator sizes = exifData.findKey(key);
- if (sizes == exifData.end()) return 2;
+ long ifdOffset = 0;
+ if (rc == 0) {
+ buflen += tiffHeader.copy(img.pData_);
+
+ // Create IFD (without Exif and GPS tags) from metadata
+ addToIfd(ifd1, exifData.begin(), exifData.end(),
+ tiffHeader.byteOrder());
+ ifd1.erase(0x8769);
+ ifd1.erase(0x8825);
+
+ // Do not copy the IFD yet, remember the location and leave a gap
+ ifdOffset = buflen;
+ buflen += ifd1.size() + ifd1.dataSize();
+ if (len < buflen) rc = 1;
+ }
+ std::string key;
+ ExifData::const_iterator offsets;
+ ExifData::const_iterator sizes;
+ if (rc == 0) {
+ // Copy thumbnail image data, remember the offsets used
+ key = "Thumbnail.RecordingOffset.StripOffsets";
+ offsets = exifData.findKey(key);
+ if (offsets == exifData.end()) rc = 2;
+ }
+ if (rc == 0) {
+ key = "Thumbnail.RecordingOffset.StripByteCounts";
+ sizes = exifData.findKey(key);
+ if (sizes == exifData.end()) rc = 2;
+ }
std::ostringstream os; // for the new strip offsets
long minOffset = 0;
- for (long k = 0; k < offsets->count(); ++k) {
- long offset = offsets->toLong(k);
- long size = sizes->toLong(k);
- memcpy(img.pData_ + len, buf + offset, size);
- os << len << " ";
- len += size;
-
- minOffset = offset; // just to initialize minOffset
- }
- for (long k = 0; k < offsets->count(); ++k) {
- minOffset = std::min(minOffset, offsets->toLong(k));
+ if (rc == 0) {
+ for (long k = 0; k < offsets->count(); ++k) {
+ long offset = offsets->toLong(k);
+ long size = sizes->toLong(k);
+ if (len < offset + size || len < buflen + size) {
+ rc = 1;
+ break;
+ }
+ memcpy(img.pData_ + buflen, buf + offset, size);
+ os << buflen << " ";
+ buflen += size;
+
+ minOffset = offset; // just to initialize minOffset
+ }
}
- // Update the IFD with the actual strip offsets (replace existing entry)
- Metadatum newOffsets(*offsets);
- newOffsets.setValue(os.str());
- ifd1.erase(0x0111);
- addToIfd(ifd1, newOffsets, tiffHeader.byteOrder());
+ if (rc == 0) {
+ for (long k = 0; k < offsets->count(); ++k) {
+ minOffset = std::min(minOffset, offsets->toLong(k));
+ }
+ // Update the IFD with the actual strip offsets (replace existing entry)
+ Metadatum newOffsets(*offsets);
+ newOffsets.setValue(os.str());
+ ifd1.erase(0x0111);
+ addToIfd(ifd1, newOffsets, tiffHeader.byteOrder());
- // Finally, sort and copy the IFD
- ifd1.sortByTag();
- ifd1.copy(img.pData_ + ifdOffset, tiffHeader.byteOrder(), ifdOffset);
+ // Finally, sort and copy the IFD
+ ifd1.sortByTag();
+ ifd1.copy(img.pData_ + ifdOffset, tiffHeader.byteOrder(), ifdOffset);
- delete[] pImage_;
- pImage_ = new char[len];
- memcpy(pImage_, img.pData_, len);
- size_ = len;
- offset_ = minOffset;
- tiffHeader_.read(pImage_);
- ifd_.read(pImage_ + tiffHeader_.offset(),
- tiffHeader_.byteOrder(), tiffHeader_.offset());
+ delete[] pImage_;
+ pImage_ = new char[buflen];
+ memcpy(pImage_, img.pData_, buflen);
+ size_ = buflen;
+ offset_ = minOffset;
+ tiffHeader_.read(pImage_);
+ rc = ifd_.read(pImage_ + tiffHeader_.offset(),
+ size_ - tiffHeader_.offset(),
+ tiffHeader_.byteOrder(), tiffHeader_.offset());
+ }
- return 0;
+ return rc;
} // TiffThumbnail::read
const char* TiffThumbnail::format() const
@@ -397,17 +422,19 @@ namespace Exiv2 {
}
int JpegThumbnail::read(const char* buf,
+ long len,
const ExifData& exifData,
ByteOrder byteOrder)
{
std::string key = "Thumbnail.RecordingOffset.JPEGInterchangeFormat";
ExifData::const_iterator pos = exifData.findKey(key);
- if (pos == exifData.end()) return 1;
+ if (pos == exifData.end()) return 2;
long offset = pos->toLong();
key = "Thumbnail.RecordingOffset.JPEGInterchangeFormatLength";
pos = exifData.findKey(key);
- if (pos == exifData.end()) return 1;
+ if (pos == exifData.end()) return 2;
long size = pos->toLong();
+ if (len < offset + size) return 1;
delete[] pImage_;
pImage_ = new char[size];
memcpy(pImage_, buf + offset, size);
@@ -540,11 +567,12 @@ namespace Exiv2 {
// Read IFD0
rc = ifd0_.read(pData_ + tiffHeader_.offset(),
+ size_ - tiffHeader_.offset(),
byteOrder(),
tiffHeader_.offset());
if (rc) return rc;
// Find and read ExifIFD sub-IFD of IFD0
- rc = ifd0_.readSubIfd(exifIfd_, pData_, byteOrder(), 0x8769);
+ rc = ifd0_.readSubIfd(exifIfd_, pData_, size_, byteOrder(), 0x8769);
if (rc) return rc;
// Find MakerNote in ExifIFD, create a MakerNote class
Ifd::iterator pos = exifIfd_.findTag(0x927c);
@@ -572,27 +600,30 @@ namespace Exiv2 {
exifIfd_.erase(pos);
}
// Find and read Interoperability IFD in ExifIFD
- rc = exifIfd_.readSubIfd(iopIfd_, pData_, byteOrder(), 0xa005);
+ rc = exifIfd_.readSubIfd(iopIfd_, pData_, size_, byteOrder(), 0xa005);
if (rc) return rc;
// Find and read GPSInfo sub-IFD in IFD0
- rc = ifd0_.readSubIfd(gpsIfd_, pData_, byteOrder(), 0x8825);
+ rc = ifd0_.readSubIfd(gpsIfd_, pData_, size_, byteOrder(), 0x8825);
if (rc) return rc;
// Read IFD1
if (ifd0_.next()) {
- rc = ifd1_.read(pData_ + ifd0_.next(), byteOrder(), ifd0_.next());
+ rc = ifd1_.read(pData_ + ifd0_.next(),
+ size_ - ifd0_.next(),
+ byteOrder(),
+ ifd0_.next());
if (rc) return rc;
}
// Find and delete ExifIFD sub-IFD of IFD1
pos = ifd1_.findTag(0x8769);
if (pos != ifd1_.end()) {
ifd1_.erase(pos);
- ret = -99;
+ ret = 7;
}
// Find and delete GPSInfo sub-IFD in IFD1
pos = ifd1_.findTag(0x8825);
if (pos != ifd1_.end()) {
ifd1_.erase(pos);
- ret = -99;
+ ret = 7;
}
// Copy all entries from the IFDs and the MakerNote to the metadata
metadata_.clear();
@@ -604,7 +635,7 @@ namespace Exiv2 {
add(iopIfd_.begin(), iopIfd_.end(), byteOrder());
add(gpsIfd_.begin(), gpsIfd_.end(), byteOrder());
add(ifd1_.begin(), ifd1_.end(), byteOrder());
- // Read the thumbnail
+ // Read the thumbnail (but don't worry whether it was successful or not)
readThumbnail();
return ret;
@@ -953,14 +984,14 @@ namespace Exiv2 {
else {
pThumbnail_ = new TiffThumbnail;
}
- rc = pThumbnail_->read(pData_, *this, byteOrder());
+ rc = pThumbnail_->read(pData_, size_, *this, byteOrder());
if (rc != 0) {
delete pThumbnail_;
pThumbnail_ = 0;
}
}
- return rc;
+ return rc;
} // ExifData::readThumbnail
bool ExifData::updateEntries()
@@ -1089,6 +1120,51 @@ namespace Exiv2 {
return ifd;
}
+ std::string ExifData::strError(int rc, const std::string& path)
+ {
+ std::string error = path + ": ";
+ switch (rc) {
+ case -1:
+ error += "Failed to open the file";
+ break;
+ case -2:
+ error += "The file contains data of an unknown image type";
+ break;
+ case -3:
+ error += "Couldn't open temporary file";
+ break;
+ case -4:
+ error += "Renaming temporary file failed";
+ break;
+ case 1:
+ error += "Couldn't read from the input stream";
+ break;
+ case 2:
+ error += "This does not look like a JPEG image";
+ break;
+ case 3:
+ error += "No Exif data found in the file";
+ break;
+ case 4:
+ error += "Writing to the output stream failed";
+ break;
+ case 5:
+ error += "No JFIF APP0 or Exif APP1 segment found in the file";
+ break;
+ case 6:
+ error += "Exif data contains a broken IFD";
+ break;
+ case 7:
+ error += "Unsupported Exif or GPS data found in IFD 1";
+ break;
+
+ default:
+ error += "Accessing Exif data failed, rc = " + toString(rc);
+ break;
+ }
+ return error;
+ } // ExifData::strError
+
// *************************************************************************
// free functions
diff --git a/src/exif.hpp b/src/exif.hpp
index f12a690..ff9035b 100644
--- a/src/exif.hpp
+++ b/src/exif.hpp
@@ -21,7 +21,7 @@
/*!
@file exif.hpp
@brief Encoding and decoding of Exif data
- @version $Name: $ $Revision: 1.43 $
+ @version $Name: $ $Revision: 1.44 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel at gmx.net">ahuggel at gmx.net</a>
@date 09-Jan-04, ahu: created
@@ -262,7 +262,8 @@ namespace Exiv2 {
metadata exifData. Return 0 if successful.
@param buf Data buffer containing the thumbnail data. The buffer must
- start with the TIFF header.
+ start with the TIFF header.
+ @param len Number of bytes in the data buffer.
@param exifData Exif data corresponding to the data buffer.
@param byteOrder The byte order used for the encoding of TIFF
thumbnails. It determines the byte order of the resulting
@@ -274,6 +275,7 @@ namespace Exiv2 {
2 in case of inconsistent TIFF thumbnail Exif data
*/
virtual int read(const char* buf,
+ long len,
const ExifData& exifData,
ByteOrder byteOrder =littleEndian) =0;
/*!
@@ -373,6 +375,7 @@ namespace Exiv2 {
//! Assignment operator.
TiffThumbnail& operator=(const TiffThumbnail& rhs);
int read(const char* buf,
+ long len,
const ExifData& exifData,
ByteOrder byteOrder =littleEndian);
void setOffsets(Ifd& ifd1, ByteOrder byteOrder);
@@ -419,6 +422,7 @@ namespace Exiv2 {
//! Assignment operator.
JpegThumbnail& operator=(const JpegThumbnail& rhs);
int read(const char* buf,
+ long len,
const ExifData& exifData,
ByteOrder byteOrder =littleEndian);
void setOffsets(Ifd& ifd1, ByteOrder byteOrder);
@@ -725,11 +729,25 @@ namespace Exiv2 {
{ return pThumbnail_ ? pThumbnail_->size() : 0; }
//@}
+ /*!
+ @brief Convert the return code from
+ int read(const std::string& path),
+ int write(const std::string& path),
+ int writeExifData(const std::string& path),
+ int writeThumbnail(const std::string& path) const and
+ int erase(const std::string& path) const
+ into an error message.
+
+ Todo: Implement global handling of error messages
+ */
+ static std::string strError(int rc, const std::string& path);
+
private:
//! @name Manipulators
//@{
/*!
- @brief Read the thumbnail from the data buffer. Return 0 if successful.
+ @brief Read the thumbnail from the data buffer. Return 0 if successful,
+ otherwise the thumbnail is deleted.
*/
int readThumbnail();
/*!
--
exiv2 packaging
More information about the pkg-kde-commits
mailing list