From 5343c93388266a352b27948ed2beb81db66f52e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= Date: Sat, 29 Sep 2018 01:30:29 +0200 Subject: [PATCH] Port Iptc::printStructure & getUshort to slices API This fixes #211, #210, #209 --- include/exiv2/iptc.hpp | 2 +- include/exiv2/types.hpp | 12 ++++++++++++ src/bigtiffimage.cpp | 19 ++++++++++++------- src/image.cpp | 23 ++++++++++++----------- src/iptc.cpp | 14 +++++++------- src/jp2image.cpp | 2 +- src/jpgimage.cpp | 4 ++-- src/pngimage.cpp | 2 +- src/types.cpp | 7 +------ 9 files changed, 49 insertions(+), 36 deletions(-) diff --git a/include/exiv2/iptc.hpp b/include/exiv2/iptc.hpp index e786a59018..f1ecee6ec1 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 13cc829566..cf10218228 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 the slice + template + EXIV2API 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 1ecfe66fbd..c67c622e5c 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,17 @@ 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 + const long read_bytes = io.read(bytes.data(), count); + io.seek(restore, BasicIo::beg); + IptcData::printStructure(out, makeSliceUntil(bytes.data(), read_bytes), depth); + } else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { diff --git a/src/image.cpp b/src/image.cpp index 515e4429ce..31b7d774c2 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" @@ -455,19 +457,18 @@ 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 + const long read_bytes = io.read(bytes.data(), count); + io.seek(restore, BasicIo::beg); + IptcData::printStructure(out, makeSliceUntil(bytes.data(), 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 71ddc65f2b..e1bece4777 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 404d610511..77045eb171 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -572,7 +572,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 bde40d1547..67f6fd049d 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 e32f87834f..90844d0953 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 6ebb2bc25b..8dce624e08 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -271,12 +271,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)