@ -9,6 +9,7 @@
# include "jpgimage.hpp"
# include "jpgimage.hpp"
# include "makernote_int.hpp"
# include "makernote_int.hpp"
# include "photoshop.hpp"
# include "photoshop.hpp"
# include "safe_op.hpp"
# include "sonymn_int.hpp"
# include "sonymn_int.hpp"
# include "tiffcomposite_int.hpp" // Do not change the order of these 2 includes,
# include "tiffcomposite_int.hpp" // Do not change the order of these 2 includes,
# include "tiffimage_int.hpp"
# include "tiffimage_int.hpp"
@ -1232,111 +1233,108 @@ void TiffReader::visitIfdMakernoteEnd(TiffIfdMakernote* /*object*/) {
} // TiffReader::visitIfdMakernoteEnd
} // TiffReader::visitIfdMakernoteEnd
void TiffReader : : readTiffEntry ( TiffEntryBase * object ) {
void TiffReader : : readTiffEntry ( TiffEntryBase * object ) {
byte * p = object - > start ( ) ;
try {
byte * p = object - > start ( ) ;
if ( p + 12 > pLast_ ) {
if ( p + 12 > pLast_ ) {
# ifndef SUPPRESS_WARNINGS
# ifndef SUPPRESS_WARNINGS
EXV_ERROR < < " Entry in directory " < < groupName ( object - > group ( ) )
EXV_ERROR < < " Entry in directory " < < groupName ( object - > group ( ) )
< < " requests access to memory beyond the data buffer. "
< < " requests access to memory beyond the data buffer. "
< < " Skipping entry. \n " ;
< < " Skipping entry. \n " ;
# endif
# endif
return ;
return ;
}
}
// Component already has tag
// Component already has tag
p + = 2 ;
p + = 2 ;
TiffType tiffType = getUShort ( p , byteOrder ( ) ) ;
TiffType tiffType = getUShort ( p , byteOrder ( ) ) ;
TypeId typeId = toTypeId ( tiffType , object - > tag ( ) , object - > group ( ) ) ;
TypeId typeId = toTypeId ( tiffType , object - > tag ( ) , object - > group ( ) ) ;
size_t typeSize = TypeInfo : : typeSize ( typeId ) ;
size_t typeSize = TypeInfo : : typeSize ( typeId ) ;
if ( 0 = = typeSize ) {
if ( 0 = = typeSize ) {
# ifndef SUPPRESS_WARNINGS
# ifndef SUPPRESS_WARNINGS
EXV_WARNING < < " Directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' )
EXV_WARNING < < " Directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' )
< < std : : hex < < object - > tag ( ) < < " has unknown Exif (TIFF) type " < < std : : dec < < tiffType
< < std : : hex < < object - > tag ( ) < < " has unknown Exif (TIFF) type " < < std : : dec < < tiffType
< < " ; setting type size 1. \n " ;
< < " ; setting type size 1. \n " ;
# endif
# endif
typeSize = 1 ;
typeSize = 1 ;
}
}
p + = 2 ;
p + = 2 ;
uint32_t count = getULong ( p , byteOrder ( ) ) ;
uint32_t count = getULong ( p , byteOrder ( ) ) ;
if ( count > = 0x10000000 ) {
if ( count > = 0x10000000 ) {
# ifndef SUPPRESS_WARNINGS
# ifndef SUPPRESS_WARNINGS
EXV_ERROR < < " Directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' )
EXV_ERROR < < " Directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' )
< < std : : hex < < object - > tag ( ) < < " has invalid size " < < std : : dec < < count < < " * " < < typeSize
< < std : : hex < < object - > tag ( ) < < " has invalid size " < < std : : dec < < count < < " * " < < typeSize
< < " ; skipping entry. \n " ;
< < " ; skipping entry. \n " ;
# endif
# endif
return ;
return ;
}
}
p + = 4 ;
p + = 4 ;
if ( count > std : : numeric_limits < uint32_t > : : max ( ) / typeSize ) {
if ( count > std : : numeric_limits < uint32_t > : : max ( ) / typeSize ) {
throw Error ( ErrorCode : : kerArithmeticOverflow ) ;
throw Error ( ErrorCode : : kerArithmeticOverflow ) ;
}
}
size_t size = typeSize * count ;
size_t size = typeSize * count ;
uint32_t offset = getULong ( p , byteOrder ( ) ) ;
uint32_t offset = getULong ( p , byteOrder ( ) ) ;
byte * pData = p ;
byte * pData = p ;
if ( size > 4 & & ( baseOffset ( ) + offset > = size_ | | baseOffset ( ) + offset < = 0 ) ) {
if ( size > 4 & & Safe : : add < size_t > ( baseOffset ( ) , offset ) > = size_ ) {
// #1143
// #1143
if ( object - > tag ( ) = = 0x2001 & & std : : string ( groupName ( object - > group ( ) ) ) = = " Sony1 " ) {
if ( object - > tag ( ) = = 0x2001 & & std : : string ( groupName ( object - > group ( ) ) ) = = " Sony1 " ) {
// This tag is Exif.Sony1.PreviewImage, which refers to a preview image which is
// This tag is Exif.Sony1.PreviewImage, which refers to a preview image which is
// not stored in the metadata. Instead it is stored at the end of the file, after
// not stored in the metadata. Instead it is stored at the end of the file, after
// the main image. The value of `size` refers to the size of the preview image, not
// the main image. The value of `size` refers to the size of the preview image, not
// the size of the tag's payload, so we set it to zero here so that we don't attempt
// the size of the tag's payload, so we set it to zero here so that we don't attempt
// to read those bytes from the metadata. We currently leave this tag as "undefined",
// to read those bytes from the metadata. We currently leave this tag as "undefined",
// although we may attempt to handle it better in the future. More discussion of
// although we may attempt to handle it better in the future. More discussion of
// this issue can be found here:
// this issue can be found here:
//
//
// https://github.com/Exiv2/exiv2/issues/2001
// https://github.com/Exiv2/exiv2/issues/2001
// https://github.com/Exiv2/exiv2/pull/2008
// https://github.com/Exiv2/exiv2/pull/2008
// https://github.com/Exiv2/exiv2/pull/2013
// https://github.com/Exiv2/exiv2/pull/2013
typeId = undefined ;
typeId = undefined ;
size = 0 ;
size = 0 ;
} else {
} else {
# ifndef SUPPRESS_WARNINGS
# ifndef SUPPRESS_WARNINGS
EXV_ERROR < < " Offset of directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 )
EXV_ERROR < < " Offset of directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 )
< < std : : setfill ( ' 0 ' ) < < std : : hex < < object - > tag ( ) < < " is out of bounds: "
< < std : : setfill ( ' 0 ' ) < < std : : hex < < object - > tag ( ) < < " is out of bounds: "
< < " Offset = 0x " < < std : : setw ( 8 ) < < std : : setfill ( ' 0 ' ) < < std : : hex < < offset
< < " Offset = 0x " < < std : : setw ( 8 ) < < std : : setfill ( ' 0 ' ) < < std : : hex < < offset
< < " ; truncating the entry \n " ;
< < " ; truncating the entry \n " ;
# endif
# endif
}
size = 0 ;
}
}
size = 0 ;
if ( size > 4 ) {
}
// setting pData to pData_ + baseOffset() + offset can result in pData pointing to invalid memory,
if ( size > 4 ) {
// as offset can be arbitrarily large
// setting pData to pData_ + baseOffset() + offset can result in pData pointing to invalid memory,
if ( Safe : : add < size_t > ( baseOffset ( ) , offset ) > static_cast < size_t > ( pLast_ - pData_ ) ) {
// as offset can be arbitrarily large
throw Error ( ErrorCode : : kerCorruptedMetadata ) ;
if ( ( static_cast < uintptr_t > ( baseOffset ( ) ) >
}
std : : numeric_limits < uintptr_t > : : max ( ) - static_cast < uintptr_t > ( offset ) ) | |
pData = const_cast < byte * > ( pData_ ) + baseOffset ( ) + offset ;
( static_cast < uintptr_t > ( baseOffset ( ) + offset ) >
std : : numeric_limits < uintptr_t > : : max ( ) - reinterpret_cast < uintptr_t > ( pData_ ) ) ) {
throw Error ( ErrorCode : : kerCorruptedMetadata ) ; // #562 don't throw kerArithmeticOverflow
}
if ( pData_ + static_cast < uintptr_t > ( baseOffset ( ) ) + static_cast < uintptr_t > ( offset ) > pLast_ ) {
throw Error ( ErrorCode : : kerCorruptedMetadata ) ;
}
pData = const_cast < byte * > ( pData_ ) + baseOffset ( ) + offset ;
// check for size being invalid
// check for size being invalid
if ( size > static_cast < size_t > ( pLast_ - pData ) ) {
if ( size > static_cast < size_t > ( pLast_ - pData ) ) {
# ifndef SUPPRESS_WARNINGS
# ifndef SUPPRESS_WARNINGS
EXV_ERROR < < " Upper boundary of data for "
EXV_ERROR < < " Upper boundary of data for "
< < " directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' )
< < " directory " < < groupName ( object - > group ( ) ) < < " , entry 0x " < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' )
< < std : : hex < < object - > tag ( ) < < " is out of bounds: "
< < std : : hex < < object - > tag ( ) < < " is out of bounds: "
< < " Offset = 0x " < < std : : setw ( 8 ) < < std : : setfill ( ' 0 ' ) < < std : : hex < < offset < < " , size = " < < std : : dec
< < " Offset = 0x " < < std : : setw ( 8 ) < < std : : setfill ( ' 0 ' ) < < std : : hex < < offset < < " , size = " < < std : : dec
< < size
< < size
< < " , exceeds buffer size by "
< < " , exceeds buffer size by "
// cast to make MSVC happy
// cast to make MSVC happy
< < static_cast < uint32_t > ( pData + size - pLast_ ) < < " Bytes; truncating the entry \n " ;
< < static_cast < uint32_t > ( pData + size - pLast_ ) < < " Bytes; truncating the entry \n " ;
# endif
# endif
size = 0 ;
size = 0 ;
}
}
}
}
auto v = Value : : create ( typeId ) ;
auto v = Value : : create ( typeId ) ;
enforce ( v ! = nullptr , ErrorCode : : kerCorruptedMetadata ) ;
enforce ( v ! = nullptr , ErrorCode : : kerCorruptedMetadata ) ;
v - > read ( pData , size , byteOrder ( ) ) ;
v - > read ( pData , size , byteOrder ( ) ) ;
object - > setValue ( std : : move ( v ) ) ;
object - > setData ( pData , size , std : : make_shared < DataBuf > ( ) ) ;
object - > setOffset ( offset ) ;
object - > setIdx ( nextIdx ( object - > group ( ) ) ) ;
object - > setValue ( std : : move ( v ) ) ;
object - > setData ( pData , size , std : : make_shared < DataBuf > ( ) ) ;
object - > setOffset ( offset ) ;
object - > setIdx ( nextIdx ( object - > group ( ) ) ) ;
} catch ( std : : overflow_error & ) {
throw Error ( ErrorCode : : kerCorruptedMetadata ) ; // #562 don't throw std::overflow_error
}
} // TiffReader::readTiffEntry
} // TiffReader::readTiffEntry
void TiffReader : : visitBinaryArray ( TiffBinaryArray * object ) {
void TiffReader : : visitBinaryArray ( TiffBinaryArray * object ) {