From 6233fa693060a8b3a6ce328d34c8bbf6f88a2a0d Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Fri, 17 Feb 2012 15:51:46 +0000 Subject: [PATCH] #810: Added sanity-checks for the minimum size of IFD makernotes before parsing. --- src/makernote.cpp | 215 +++++++++++++++++++++++++++--------------- src/makernote_int.hpp | 18 ++-- 2 files changed, 148 insertions(+), 85 deletions(-) diff --git a/src/makernote.cpp b/src/makernote.cpp index 4df3fa8a..3a83183f 100644 --- a/src/makernote.cpp +++ b/src/makernote.cpp @@ -162,11 +162,15 @@ namespace Exiv2 { const byte OlympusMnHeader::signature_[] = { 'O', 'L', 'Y', 'M', 'P', 0x00, 0x01, 0x00 }; - const uint32_t OlympusMnHeader::size_ = 8; + + uint32_t OlympusMnHeader::sizeOfSignature() + { + return sizeof(signature_); + } OlympusMnHeader::OlympusMnHeader() { - read(signature_, size_, invalidByteOrder); + read(signature_, sizeOfSignature(), invalidByteOrder); } OlympusMnHeader::~OlympusMnHeader() @@ -180,17 +184,17 @@ namespace Exiv2 { uint32_t OlympusMnHeader::ifdOffset() const { - return size_; + return sizeOfSignature(); } bool OlympusMnHeader::read(const byte* pData, uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; - header_.alloc(size_); + if (!pData || size < sizeOfSignature()) return false; + header_.alloc(sizeOfSignature()); std::memcpy(header_.pData_, pData, header_.size_); - if ( static_cast(header_.size_) < size_ + if ( static_cast(header_.size_) < sizeOfSignature() || 0 != memcmp(header_.pData_, signature_, 6)) { return false; } @@ -200,18 +204,22 @@ namespace Exiv2 { uint32_t OlympusMnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // OlympusMnHeader::write const byte Olympus2MnHeader::signature_[] = { 'O', 'L', 'Y', 'M', 'P', 'U', 'S', 0x00, 'I', 'I', 0x03, 0x00 }; - const uint32_t Olympus2MnHeader::size_ = 12; + + uint32_t Olympus2MnHeader::sizeOfSignature() + { + return sizeof(signature_); + } Olympus2MnHeader::Olympus2MnHeader() { - read(signature_, size_, invalidByteOrder); + read(signature_, sizeOfSignature(), invalidByteOrder); } Olympus2MnHeader::~Olympus2MnHeader() @@ -225,7 +233,7 @@ namespace Exiv2 { uint32_t Olympus2MnHeader::ifdOffset() const { - return size_; + return sizeOfSignature(); } uint32_t Olympus2MnHeader::baseOffset(uint32_t mnOffset) const @@ -237,10 +245,10 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; - header_.alloc(size_); + if (!pData || size < sizeOfSignature()) return false; + header_.alloc(sizeOfSignature()); std::memcpy(header_.pData_, pData, header_.size_); - if ( static_cast(header_.size_) < size_ + if ( static_cast(header_.size_) < sizeOfSignature() || 0 != memcmp(header_.pData_, signature_, 10)) { return false; } @@ -250,19 +258,23 @@ namespace Exiv2 { uint32_t Olympus2MnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // Olympus2MnHeader::write const byte FujiMnHeader::signature_[] = { 'F', 'U', 'J', 'I', 'F', 'I', 'L', 'M', 0x0c, 0x00, 0x00, 0x00 }; - const uint32_t FujiMnHeader::size_ = 12; const ByteOrder FujiMnHeader::byteOrder_ = littleEndian; + uint32_t FujiMnHeader::sizeOfSignature() + { + return sizeof(signature_); + } + FujiMnHeader::FujiMnHeader() { - read(signature_, size_, byteOrder_); + read(signature_, sizeOfSignature(), byteOrder_); } FujiMnHeader::~FujiMnHeader() @@ -293,13 +305,13 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; - header_.alloc(size_); + if (!pData || size < sizeOfSignature()) return false; + header_.alloc(sizeOfSignature()); std::memcpy(header_.pData_, pData, header_.size_); // Read offset to the IFD relative to the start of the makernote // from the header. Note that we ignore the byteOrder argument start_ = getULong(header_.pData_ + 8, byteOrder_); - if ( static_cast(header_.size_) < size_ + if ( static_cast(header_.size_) < sizeOfSignature() || 0 != memcmp(header_.pData_, signature_, 8)) { return false; } @@ -309,18 +321,22 @@ namespace Exiv2 { uint32_t FujiMnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // FujiMnHeader::write const byte Nikon2MnHeader::signature_[] = { 'N', 'i', 'k', 'o', 'n', '\0', 0x01, 0x00 }; - const uint32_t Nikon2MnHeader::size_ = 8; + + uint32_t Nikon2MnHeader::sizeOfSignature() + { + return sizeof(signature_); + } Nikon2MnHeader::Nikon2MnHeader() { - read(signature_, size_, invalidByteOrder); + read(signature_, sizeOfSignature(), invalidByteOrder); } Nikon2MnHeader::~Nikon2MnHeader() @@ -329,7 +345,7 @@ namespace Exiv2 { uint32_t Nikon2MnHeader::size() const { - return size_; + return sizeOfSignature(); } uint32_t Nikon2MnHeader::ifdOffset() const @@ -341,33 +357,37 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; + if (!pData || size < sizeOfSignature()) return false; if (0 != memcmp(pData, signature_, 6)) return false; - buf_.alloc(size_); + buf_.alloc(sizeOfSignature()); std::memcpy(buf_.pData_, pData, buf_.size_); - start_ = size_; + start_ = sizeOfSignature(); return true; } // Nikon2MnHeader::read uint32_t Nikon2MnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // Nikon2MnHeader::write const byte Nikon3MnHeader::signature_[] = { 'N', 'i', 'k', 'o', 'n', '\0', 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const uint32_t Nikon3MnHeader::size_ = 18; + + uint32_t Nikon3MnHeader::sizeOfSignature() + { + return sizeof(signature_); + } Nikon3MnHeader::Nikon3MnHeader() { - buf_.alloc(size_); + buf_.alloc(sizeOfSignature()); std::memcpy(buf_.pData_, signature_, buf_.size_); byteOrder_ = invalidByteOrder; - start_ = size_; + start_ = sizeOfSignature(); } Nikon3MnHeader::~Nikon3MnHeader() @@ -376,7 +396,7 @@ namespace Exiv2 { uint32_t Nikon3MnHeader::size() const { - return size_; + return sizeOfSignature(); } uint32_t Nikon3MnHeader::ifdOffset() const @@ -398,9 +418,9 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; + if (!pData || size < sizeOfSignature()) return false; if (0 != memcmp(pData, signature_, 6)) return false; - buf_.alloc(size_); + buf_.alloc(sizeOfSignature()); std::memcpy(buf_.pData_, pData, buf_.size_); TiffHeader th; if (!th.read(buf_.pData_ + 10, 8)) return false; @@ -431,11 +451,15 @@ namespace Exiv2 { const byte PanasonicMnHeader::signature_[] = { 'P', 'a', 'n', 'a', 's', 'o', 'n', 'i', 'c', 0x00, 0x00, 0x00 }; - const uint32_t PanasonicMnHeader::size_ = 12; + + uint32_t PanasonicMnHeader::sizeOfSignature() + { + return sizeof(signature_); + } PanasonicMnHeader::PanasonicMnHeader() { - read(signature_, size_, invalidByteOrder); + read(signature_, sizeOfSignature(), invalidByteOrder); } PanasonicMnHeader::~PanasonicMnHeader() @@ -444,7 +468,7 @@ namespace Exiv2 { uint32_t PanasonicMnHeader::size() const { - return size_; + return sizeOfSignature(); } uint32_t PanasonicMnHeader::ifdOffset() const @@ -456,29 +480,33 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; + if (!pData || size < sizeOfSignature()) return false; if (0 != memcmp(pData, signature_, 9)) return false; - buf_.alloc(size_); + buf_.alloc(sizeOfSignature()); std::memcpy(buf_.pData_, pData, buf_.size_); - start_ = size_; + start_ = sizeOfSignature(); return true; } // PanasonicMnHeader::read uint32_t PanasonicMnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // PanasonicMnHeader::write const byte PentaxMnHeader::signature_[] = { 'A', 'O', 'C', 0x00, 'M', 'M' }; - const uint32_t PentaxMnHeader::size_ = 6; + + uint32_t PentaxMnHeader::sizeOfSignature() + { + return sizeof(signature_); + } PentaxMnHeader::PentaxMnHeader() { - read(signature_, size_, invalidByteOrder); + read(signature_, sizeOfSignature(), invalidByteOrder); } PentaxMnHeader::~PentaxMnHeader() @@ -492,17 +520,17 @@ namespace Exiv2 { uint32_t PentaxMnHeader::ifdOffset() const { - return size_; + return sizeOfSignature(); } bool PentaxMnHeader::read(const byte* pData, uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; - header_.alloc(size_); + if (!pData || size < sizeOfSignature()) return false; + header_.alloc(sizeOfSignature()); std::memcpy(header_.pData_, pData, header_.size_); - if ( static_cast(header_.size_) < size_ + if ( static_cast(header_.size_) < sizeOfSignature() || 0 != memcmp(header_.pData_, signature_, 3)) { return false; } @@ -512,8 +540,8 @@ namespace Exiv2 { uint32_t PentaxMnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // PentaxMnHeader::write SamsungMnHeader::SamsungMnHeader() @@ -550,11 +578,16 @@ namespace Exiv2 { const byte SigmaMnHeader::signature2_[] = { 'F', 'O', 'V', 'E', 'O', 'N', '\0', '\0', 0x01, 0x00 }; - const uint32_t SigmaMnHeader::size_ = 10; + + uint32_t SigmaMnHeader::sizeOfSignature() + { + assert(sizeof(signature1_) == sizeof(signature2_)); + return sizeof(signature1_); + } SigmaMnHeader::SigmaMnHeader() { - read(signature1_, size_, invalidByteOrder); + read(signature1_, sizeOfSignature(), invalidByteOrder); } SigmaMnHeader::~SigmaMnHeader() @@ -563,7 +596,7 @@ namespace Exiv2 { uint32_t SigmaMnHeader::size() const { - return size_; + return sizeOfSignature(); } uint32_t SigmaMnHeader::ifdOffset() const @@ -575,30 +608,34 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; + if (!pData || size < sizeOfSignature()) return false; if ( 0 != memcmp(pData, signature1_, 8) && 0 != memcmp(pData, signature2_, 8)) return false; - buf_.alloc(size_); + buf_.alloc(sizeOfSignature()); std::memcpy(buf_.pData_, pData, buf_.size_); - start_ = size_; + start_ = sizeOfSignature(); return true; } // SigmaMnHeader::read uint32_t SigmaMnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature1_, size_); - return size_; + ioWrapper.write(signature1_, sizeOfSignature()); + return sizeOfSignature(); } // SigmaMnHeader::write const byte SonyMnHeader::signature_[] = { 'S', 'O', 'N', 'Y', ' ', 'D', 'S', 'C', ' ', '\0', '\0', '\0' }; - const uint32_t SonyMnHeader::size_ = 12; + + uint32_t SonyMnHeader::sizeOfSignature() + { + return sizeof(signature_); + } SonyMnHeader::SonyMnHeader() { - read(signature_, size_, invalidByteOrder); + read(signature_, sizeOfSignature(), invalidByteOrder); } SonyMnHeader::~SonyMnHeader() @@ -607,7 +644,7 @@ namespace Exiv2 { uint32_t SonyMnHeader::size() const { - return size_; + return sizeOfSignature(); } uint32_t SonyMnHeader::ifdOffset() const @@ -619,19 +656,19 @@ namespace Exiv2 { uint32_t size, ByteOrder /*byteOrder*/) { - if (!pData || size < size_) return false; - if (0 != memcmp(pData, signature_, size_)) return false; - buf_.alloc(size_); + if (!pData || size < sizeOfSignature()) return false; + if (0 != memcmp(pData, signature_, sizeOfSignature())) return false; + buf_.alloc(sizeOfSignature()); std::memcpy(buf_.pData_, pData, buf_.size_); - start_ = size_; + start_ = sizeOfSignature(); return true; } // SonyMnHeader::read uint32_t SonyMnHeader::write(IoWrapper& ioWrapper, ByteOrder /*byteOrder*/) const { - ioWrapper.write(signature_, size_); - return size_; + ioWrapper.write(signature_, sizeOfSignature()); + return sizeOfSignature(); } // SonyMnHeader::write // ************************************************************************* @@ -641,9 +678,11 @@ namespace Exiv2 { IfdId group, IfdId mnGroup, const byte* /*pData*/, - uint32_t /*size*/, + uint32_t size, ByteOrder /*byteOrder*/) { + // Require at least an IFD with 1 entry, but not necessarily a next pointer + if (size < 14) return 0; return newIfdMn2(tag, group, mnGroup); } @@ -663,8 +702,12 @@ namespace Exiv2 { { if (size < 10 || std::string(reinterpret_cast(pData), 10) != std::string("OLYMPUS\0II", 10)) { + // Require at least the header and an IFD with 1 entry + if (size < OlympusMnHeader::sizeOfSignature() + 18) return 0; return newOlympusMn2(tag, group, olympusId); } + // Require at least the header and an IFD with 1 entry + if (size < Olympus2MnHeader::sizeOfSignature() + 18) return 0; return newOlympus2Mn2(tag, group, olympus2Id); } @@ -686,9 +729,11 @@ namespace Exiv2 { IfdId group, IfdId mnGroup, const byte* /*pData*/, - uint32_t /*size*/, + uint32_t size, ByteOrder /*byteOrder*/) { + // Require at least the header and an IFD with 1 entry + if (size < FujiMnHeader::sizeOfSignature() + 18) return 0; return newFujiMn2(tag, group, mnGroup); } @@ -709,6 +754,8 @@ namespace Exiv2 { // If there is no "Nikon" string it must be Nikon1 format if (size < 6 || std::string(reinterpret_cast(pData), 6) != std::string("Nikon\0", 6)) { + // Require at least an IFD with 1 entry + if (size < 18) return 0; return newIfdMn2(tag, group, nikon1Id); } // If the "Nikon" string is not followed by a TIFF header, we assume @@ -717,9 +764,13 @@ namespace Exiv2 { if ( size < 18 || !tiffHeader.read(pData + 10, size - 10) || tiffHeader.tag() != 0x002a) { + // Require at least the header and an IFD with 1 entry + if (size < Nikon2MnHeader::sizeOfSignature() + 18) return 0; return newNikon2Mn2(tag, group, nikon2Id); } // Else we have a Nikon3 makernote + // Require at least the header and an IFD with 1 entry + if (size < Nikon3MnHeader::sizeOfSignature() + 18) return 0; return newNikon3Mn2(tag, group, nikon3Id); } @@ -741,9 +792,11 @@ namespace Exiv2 { IfdId group, IfdId mnGroup, const byte* /*pData*/, - uint32_t /*size*/, + uint32_t size, ByteOrder /*byteOrder*/) { + // Require at least the header and an IFD with 1 entry, but without a next pointer + if (size < PanasonicMnHeader::sizeOfSignature() + 14) return 0; return newPanasonicMn2(tag, group, mnGroup); } @@ -758,9 +811,11 @@ namespace Exiv2 { IfdId group, IfdId mnGroup, const byte* /*pData*/, - uint32_t /*size*/, + uint32_t size, ByteOrder /*byteOrder*/) { + // Require at least the header and an IFD with 1 entry + if (size < PentaxMnHeader::sizeOfSignature() + 18) return 0; return newPentaxMn2(tag, group, mnGroup); } @@ -775,9 +830,11 @@ namespace Exiv2 { IfdId group, IfdId mnGroup, const byte* /*pData*/, - uint32_t /*size*/, + uint32_t size, ByteOrder /*byteOrder*/) { + // Require at least an IFD with 1 entry + if (size < 18) return 0; return newSamsungMn2(tag, group, mnGroup); } @@ -792,9 +849,11 @@ namespace Exiv2 { IfdId group, IfdId mnGroup, const byte* /*pData*/, - uint32_t /*size*/, + uint32_t size, ByteOrder /*byteOrder*/) { + // Require at least the header and an IFD with 1 entry + if (size < SigmaMnHeader::sizeOfSignature() + 18) return 0; return newSigmaMn2(tag, group, mnGroup); } @@ -815,8 +874,12 @@ namespace Exiv2 { // If there is no "SONY DSC " string we assume it's a simple IFD Makernote if (size < 12 || std::string(reinterpret_cast(pData), 12) != std::string("SONY DSC \0\0\0", 12)) { + // Require at least an IFD with 1 entry + if (size < 18) return 0; return newSony2Mn2(tag, group, sony2Id); } + // Require at least the header and an IFD with 1 entry, but without a next pointer + if (size < SonyMnHeader::sizeOfSignature() + 14) return 0; return newSony1Mn2(tag, group, sony1Id); } diff --git a/src/makernote_int.hpp b/src/makernote_int.hpp index cc2c312f..ab9f77ba 100644 --- a/src/makernote_int.hpp +++ b/src/makernote_int.hpp @@ -190,11 +190,11 @@ namespace Exiv2 { virtual uint32_t write(IoWrapper& ioWrapper, ByteOrder byteOrder) const; virtual uint32_t ifdOffset() const; //@} + static uint32_t sizeOfSignature(); private: DataBuf header_; //!< Data buffer for the makernote header static const byte signature_[]; //!< Olympus makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class OlympusMnHeader @@ -221,11 +221,11 @@ namespace Exiv2 { virtual uint32_t ifdOffset() const; virtual uint32_t baseOffset(uint32_t mnOffset) const; //@} + static uint32_t sizeOfSignature(); private: DataBuf header_; //!< Data buffer for the makernote header static const byte signature_[]; //!< Olympus makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class Olympus2MnHeader @@ -254,11 +254,11 @@ namespace Exiv2 { virtual ByteOrder byteOrder() const; virtual uint32_t baseOffset(uint32_t mnOffset) const; //@} + static uint32_t sizeOfSignature(); private: DataBuf header_; //!< Data buffer for the makernote header static const byte signature_[]; //!< Fujifilm makernote header signature - static const uint32_t size_; //!< Size of the signature static const ByteOrder byteOrder_; //!< Byteorder for makernote (always II) uint32_t start_; //!< Start of the mn IFD rel. to mn start @@ -286,12 +286,12 @@ namespace Exiv2 { virtual uint32_t write(IoWrapper& ioWrapper, ByteOrder byteOrder) const; virtual uint32_t ifdOffset() const; //@} + static uint32_t sizeOfSignature(); private: DataBuf buf_; //!< Raw header data uint32_t start_; //!< Start of the mn IFD rel. to mn start static const byte signature_[]; //!< Nikon 2 makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class Nikon2MnHeader @@ -320,13 +320,13 @@ namespace Exiv2 { virtual ByteOrder byteOrder() const; virtual uint32_t baseOffset(uint32_t mnOffset) const; //@} + static uint32_t sizeOfSignature(); private: DataBuf buf_; //!< Raw header data ByteOrder byteOrder_; //!< Byteorder for makernote uint32_t start_; //!< Start of the mn IFD rel. to mn start static const byte signature_[]; //!< Nikon 3 makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class Nikon3MnHeader @@ -352,12 +352,12 @@ namespace Exiv2 { virtual uint32_t write(IoWrapper& ioWrapper, ByteOrder byteOrder) const; virtual uint32_t ifdOffset() const; //@} + static uint32_t sizeOfSignature(); private: DataBuf buf_; //!< Raw header data uint32_t start_; //!< Start of the mn IFD rel. to mn start static const byte signature_[]; //!< Panasonic makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class PanasonicMnHeader @@ -383,11 +383,11 @@ namespace Exiv2 { virtual uint32_t write(IoWrapper& ioWrapper, ByteOrder byteOrder) const; virtual uint32_t ifdOffset() const; //@} + static uint32_t sizeOfSignature(); private: DataBuf header_; //!< Data buffer for the makernote header static const byte signature_[]; //!< Pentax makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class PentaxMnHeader @@ -436,13 +436,13 @@ namespace Exiv2 { virtual uint32_t write(IoWrapper& ioWrapper, ByteOrder byteOrder) const; virtual uint32_t ifdOffset() const; //@} + static uint32_t sizeOfSignature(); private: DataBuf buf_; //!< Raw header data uint32_t start_; //!< Start of the mn IFD rel. to mn start static const byte signature1_[]; //!< Sigma makernote header signature 1 static const byte signature2_[]; //!< Sigma makernote header signature 2 - static const uint32_t size_; //!< Size of the signature }; // class SigmaMnHeader @@ -468,12 +468,12 @@ namespace Exiv2 { virtual uint32_t write(IoWrapper& ioWrapper, ByteOrder byteOrder) const; virtual uint32_t ifdOffset() const; //@} + static uint32_t sizeOfSignature(); private: DataBuf buf_; //!< Raw header data uint32_t start_; //!< Start of the mn IFD rel. to mn start static const byte signature_[]; //!< Sony makernote header signature - static const uint32_t size_; //!< Size of the signature }; // class SonyMnHeader