diff --git a/include/exiv2/value.hpp b/include/exiv2/value.hpp index 2078c6bdbb..b7d76fefde 100644 --- a/include/exiv2/value.hpp +++ b/include/exiv2/value.hpp @@ -1659,11 +1659,13 @@ namespace Exiv2 { ok_ = true; return static_cast(value_[n]); } +// #55 crash when value_[n].first == LONG_MIN +#define LARGE_INT 1000000 // Specialization for rational template<> inline long ValueType::toLong(long n) const { - ok_ = (value_[n].second != 0 && INT_MIN < value_[n].first && value_[n].first < INT_MAX ); + ok_ = (value_[n].second != 0 && -LARGE_INT < value_[n].first && value_[n].first < LARGE_INT); if (!ok_) return 0; return value_[n].first / value_[n].second; } @@ -1671,7 +1673,7 @@ namespace Exiv2 { template<> inline long ValueType::toLong(long n) const { - ok_ = (value_[n].second != 0); + ok_ = (value_[n].second != 0 && value_[n].first < LARGE_INT); if (!ok_) return 0; return value_[n].first / value_[n].second; } diff --git a/src/basicio.cpp b/src/basicio.cpp index 28aa454db6..9c5c04cafc 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -990,6 +990,7 @@ namespace Exiv2 { DataBuf FileIo::read(long rcount) { assert(p_->fp_ != 0); + if ( (size_t) rcount > size() ) throw Error(57); DataBuf buf(rcount); long readCount = read(buf.pData_, buf.size_); buf.size_ = readCount; diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 7c64a0d5cc..d5813ad006 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -226,14 +226,20 @@ namespace Exiv2 : is8ByteType(type) ? 8 : 1; - DataBuf buf(size * count + pad); + // #55 memory allocation crash test/data/POC8 + long long allocate = (long long) (size*count + pad); + if ( allocate > (long long) io.size() ) { + throw Error(57); + } + + DataBuf buf(allocate); const uint64_t offset = header_.format() == Header::StandardTiff? byteSwap4(data, 0, doSwap_): byteSwap8(data, 0, doSwap_); // big data? Use 'data' as pointer to real data - const bool usePointer = count*size > dataSize_; + const bool usePointer = (size_t) count*size > (size_t) dataSize_; if ( usePointer ) // read into buffer { diff --git a/src/error.cpp b/src/error.cpp index 6ca8917d9a..e90a9c0ac8 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -106,8 +106,9 @@ namespace { { 52, N_("%1 has invalid XMP value type `%2'") }, // %1=key, %2=value type { 53, N_("Not a valid ICC Profile") }, { 54, N_("Not valid XMP") }, - { 55, N_("tiff directory length is too large") }, + { 55, N_("tiff directory length is too large") }, { 56, N_("invalid type value detected in Image::printIFDStructure") }, + { 57, N_("invalid memory allocation request") }, }; } diff --git a/src/image.cpp b/src/image.cpp index 0fe268d87b..4c6dd07a78 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -400,7 +400,13 @@ namespace Exiv2 { ; // if ( offset > io.size() ) offset = 0; // Denial of service? - DataBuf buf(size*count + pad+20); // allocate a buffer + + // #55 memory allocation crash test/data/POC8 + long long allocate = (long long) (size*count + pad+20); + if ( allocate > (long long) io.size() ) { + throw Error(57); + } + DataBuf buf(allocate); // allocate a buffer std::memcpy(buf.pData_,dir.pData_+8,4); // copy dir[8:11] into buffer (short strings) const bool bOffsetIsPointer = count*size > 4; diff --git a/test/data/bugfixes-test.out b/test/data/bugfixes-test.out index 3bcd776b78..6304c0fcbf 100644 Binary files a/test/data/bugfixes-test.out and b/test/data/bugfixes-test.out differ