diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp index 2e0d894e..5b87a97b 100644 --- a/src/tiffvisitor.cpp +++ b/src/tiffvisitor.cpp @@ -1099,6 +1099,21 @@ namespace Exiv2 { } } + bool TiffReader::circularReference(const byte* start, uint16_t group) + { + DirList::const_iterator pos = dirList_.find(start); + if (pos != dirList_.end()) { +#ifndef SUPPRESS_WARNINGS + std::cerr << "Error: " + << tiffGroupName(group) << " pointer references previously read " + << tiffGroupName(pos->second) << " directory. Ignored.\n"; +#endif + return true; + } + dirList_[start] = group; + return false; + } + void TiffReader::visitDirectory(TiffDirectory* object) { assert(object != 0); @@ -1106,6 +1121,8 @@ namespace Exiv2 { const byte* p = object->start(); assert(p >= pData_); + if (circularReference(object->start(), object->group())) return; + if (p + 2 > pLast_) { #ifndef SUPPRESS_WARNINGS std::cerr << "Error: " diff --git a/src/tiffvisitor_int.hpp b/src/tiffvisitor_int.hpp index 97ea0fc7..cea28600 100644 --- a/src/tiffvisitor_int.hpp +++ b/src/tiffvisitor_int.hpp @@ -613,6 +613,8 @@ namespace Exiv2 { void changeState(TiffRwState::AutoPtr state); //! Reset the state to the original state as set in the constructor. void resetState(); + //! Check IFD directory pointer \em start for circular reference + bool circularReference(const byte* start, uint16_t group); //@} //! @name Accessors @@ -627,6 +629,8 @@ namespace Exiv2 { //@} private: + typedef std::map DirList; + // DATA const byte* pData_; //!< Pointer to the memory buffer const uint32_t size_; //!< Size of the buffer @@ -634,6 +638,7 @@ namespace Exiv2 { TiffComponent* const pRoot_; //!< Root element of the composite TiffRwState* pState_; //!< State class TiffRwState* pOrigState_; //!< State class as set in the c'tor + DirList dirList_; //!< List of IFD pointers and their groups }; // class TiffReader