diff --git a/include/exiv2/iptc.hpp b/include/exiv2/iptc.hpp index e786a590..f1ecee6e 100644 --- a/include/exiv2/iptc.hpp +++ b/include/exiv2/iptc.hpp @@ -274,7 +274,7 @@ namespace Exiv2 { /*! @brief dump iptc formatted binary data (used by printStructure kpsRecursive) */ - static void printStructure(std::ostream& out, const byte* bytes,const size_t size,uint32_t depth); + static void printStructure(std::ostream& out, const Slice& bytes,uint32_t depth); //@} private: diff --git a/include/exiv2/types.hpp b/include/exiv2/types.hpp index 13cc8295..ece9ef62 100644 --- a/include/exiv2/types.hpp +++ b/include/exiv2/types.hpp @@ -33,6 +33,7 @@ #include "config.h" #include "slice.hpp" #include "exiv2lib_export.h" +#include "slice.hpp" // + standard includes #include @@ -296,6 +297,17 @@ namespace Exiv2 { //! Read a 2 byte unsigned short value from the data buffer EXIV2API uint16_t getUShort(const byte* buf, ByteOrder byteOrder); + //! Read a 2 byte unsigned short value from a Slice + template + uint16_t getUShort(const Slice& buf, ByteOrder byteOrder) + { + if (byteOrder == littleEndian) { + return static_cast(buf.at(1)) << 8 | static_cast(buf.at(0)); + } else { + return static_cast(buf.at(0)) << 8 | static_cast(buf.at(1)); + } + } + //! Read a 4 byte unsigned long value from the data buffer EXIV2API uint32_t getULong(const byte* buf, ByteOrder byteOrder); //! Read a 8 byte unsigned long value from the data buffer diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 1ecfe66f..1fda1731 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -4,6 +4,7 @@ #include #include +#include "safe_op.hpp" #include "exif.hpp" #include "error.hpp" #include "image_int.hpp" @@ -355,13 +356,19 @@ namespace Exiv2 } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { - const size_t restore = io.tell(); // save - io.seek(offset, BasicIo::beg); // position - byte* bytes=new byte[(size_t)count] ; // allocate memory - io.read(bytes,(long)count) ; // read - io.seek(restore, BasicIo::beg); // restore - IptcData::printStructure(out,bytes,(size_t)count,depth); - delete[] bytes; // free + if (Safe::add(count, offset) > io.size()) { + throw Error(kerCorruptedMetadata); + } + + const size_t restore = io.tell(); + io.seek(offset, BasicIo::beg); // position + std::vector bytes(count) ; // allocate memory + // TODO: once we have C++11 use bytes.data() + const long read_bytes = io.read(&bytes[0], static_cast(count)); + io.seek(restore, BasicIo::beg); + // TODO: once we have C++11 use bytes.data() + IptcData::printStructure(out, makeSliceUntil(&bytes[0], read_bytes), depth); + } else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { diff --git a/src/image.cpp b/src/image.cpp index f95ddc13..e0eebf3d 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -28,6 +28,8 @@ #include "image_int.hpp" #include "error.hpp" #include "futils.hpp" +#include "safe_op.hpp" +#include "slice.hpp" #include "cr2image.hpp" #include "crwimage.hpp" @@ -454,19 +456,20 @@ namespace Exiv2 { io.seek(restore,BasicIo::beg); } } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { - if (offset > std::numeric_limits::max() - count) { - throw Error(kerArithmeticOverflow); - } - if (static_cast(offset + count) > io.size()) { + + if (static_cast(Safe::add(count, offset)) > io.size()) { throw Error(kerCorruptedMetadata); } - size_t restore = io.tell(); // save - io.seek(offset,BasicIo::beg); // position - byte* bytes=new byte[count] ; // allocate memory - io.read(bytes,count) ; // read - io.seek(restore,BasicIo::beg); // restore - IptcData::printStructure(out,bytes,count,depth); - delete[] bytes; // free + + const size_t restore = io.tell(); + io.seek(offset, BasicIo::beg); // position + std::vector bytes(count) ; // allocate memory + // TODO: once we have C++11 use bytes.data() + const long read_bytes = io.read(&bytes[0], count); + io.seek(restore, BasicIo::beg); + // TODO: once we have C++11 use bytes.data() + IptcData::printStructure(out, makeSliceUntil(&bytes[0], read_bytes), depth); + } else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { size_t restore = io.tell(); // save diff --git a/src/iptc.cpp b/src/iptc.cpp index 71ddc65f..e1bece47 100644 --- a/src/iptc.cpp +++ b/src/iptc.cpp @@ -347,21 +347,21 @@ namespace Exiv2 { return iptcMetadata_.erase(pos); } - void IptcData::printStructure(std::ostream& out, const byte* bytes, const size_t size, uint32_t depth) + void IptcData::printStructure(std::ostream& out, const Slice& bytes, uint32_t depth) { uint32_t i = 0; - while (i < size - 3 && bytes[i] != 0x1c) + while (i < bytes.size() - 3 && bytes.at(i) != 0x1c) i++; depth++; out << Internal::indent(depth) << "Record | DataSet | Name | Length | Data" << std::endl; - while (i < size - 3) { - if (bytes[i] != 0x1c) { + while (i < bytes.size() - 3) { + if (bytes.at(i) != 0x1c) { break; } char buff[100]; - uint16_t record = bytes[i + 1]; - uint16_t dataset = bytes[i + 2]; - uint16_t len = getUShort(bytes + i + 3, bigEndian); + uint16_t record = bytes.at(i + 1); + uint16_t dataset = bytes.at(i + 2); + uint16_t len = getUShort(bytes.subSlice(i + 3, bytes.size()), bigEndian); sprintf(buff, " %6d | %7d | %-24s | %6d | ", record, dataset, Exiv2::IptcDataSets::dataSetName(dataset, record).c_str(), len); diff --git a/src/jp2image.cpp b/src/jp2image.cpp index 27691044..35d9d6e4 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -576,7 +576,7 @@ namespace Exiv2 if(bIsIPTC && bRecursive) { - IptcData::printStructure(out,rawData.pData_,rawData.size_,depth); + IptcData::printStructure(out, makeSlice(rawData.pData_, 0, rawData.size_), depth); } if( bIsXMP && bXMP ) diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index bde40d15..67f6fd04 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -637,7 +637,7 @@ namespace Exiv2 { throw Error(kerFailedToReadImageData); if (bufRead < 2) throw Error(kerNotAJpeg); - uint16_t size = mHasLength[marker] ? getUShort(buf.pData_, bigEndian) : 0; + const uint16_t size = mHasLength[marker] ? getUShort(buf.pData_, bigEndian) : 0; if (bPrint && mHasLength[marker]) out << Internal::stringFormat(" | %7d ", size); @@ -780,7 +780,7 @@ namespace Exiv2 { } if (bPS) { - IptcData::printStructure(out, exif, size, depth); + IptcData::printStructure(out, makeSlice(exif, 0, size), depth); } else { // create a copy on write memio object with the data, then print the structure BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(exif + start, size - start)); diff --git a/src/pngimage.cpp b/src/pngimage.cpp index e32f8783..90844d09 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -356,7 +356,7 @@ namespace Exiv2 { printTiffStructure(*p,out,option,depth); } if ( bIptc ) { - IptcData::printStructure(out,parsedBuf.pData_,parsedBuf.size_,depth); + IptcData::printStructure(out, makeSlice(parsedBuf.pData_, 0, parsedBuf.size_), depth); } } } diff --git a/src/types.cpp b/src/types.cpp index bc029903..b574f5d6 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -276,12 +276,7 @@ namespace Exiv2 { uint16_t getUShort(const byte* buf, ByteOrder byteOrder) { - if (byteOrder == littleEndian) { - return (byte)buf[1] << 8 | (byte)buf[0]; - } - else { - return (byte)buf[0] << 8 | (byte)buf[1]; - } + return getUShort(makeSliceUntil(buf, 2), byteOrder); } uint32_t getULong(const byte* buf, ByteOrder byteOrder)