From bf6546ee827c578b043e3f46d5c0fd6ef3949311 Mon Sep 17 00:00:00 2001 From: Mohamed Ali Chebbi Date: Sun, 5 Feb 2023 00:11:03 +0100 Subject: [PATCH] add test/data for video support : restore Riff HeaderReader and reserve addtional byte in readStraingTag --- include/exiv2/riffvideo.hpp | 20 +++++++++- src/helper_functions.cpp | 3 +- src/riffvideo.cpp | 78 +++++++++++++++++++------------------ 3 files changed, 61 insertions(+), 40 deletions(-) diff --git a/include/exiv2/riffvideo.hpp b/include/exiv2/riffvideo.hpp index 6d70f763..e4677158 100644 --- a/include/exiv2/riffvideo.hpp +++ b/include/exiv2/riffvideo.hpp @@ -52,9 +52,25 @@ class EXIV2API RiffVideo : public Image { //@} protected: - void readList(uint64_t size); + class HeaderReader { + std::string id_ = ""; + uint64_t size_ = 0; - void readChunk(uint64_t size, const std::string& id); + public: + explicit HeaderReader(BasicIo::UniquePtr& io); + + [[nodiscard]] uint64_t getSize() const { + return size_; + } + + [[nodiscard]] std::string& getId() { + return id_; + } + }; + + void readList(HeaderReader& header_); + + void readChunk(HeaderReader& header_); void decodeBlocks(); diff --git a/src/helper_functions.cpp b/src/helper_functions.cpp index ccb9c05f..faa3209e 100644 --- a/src/helper_functions.cpp +++ b/src/helper_functions.cpp @@ -63,7 +63,8 @@ std::string readStringWcharTag(BasicIo::UniquePtr& io, size_t length) { std::string readStringTag(BasicIo::UniquePtr& io, size_t length) { Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata); - DataBuf FieldBuf = io->read(length); + DataBuf FieldBuf(length + 1); + io->readOrThrow(FieldBuf.data(), length, ErrorCode::kerFailedToReadImageData); return Exiv2::toString(FieldBuf.data()).substr(0, length); } diff --git a/src/riffvideo.cpp b/src/riffvideo.cpp index c1bf6e26..0cc935c3 100644 --- a/src/riffvideo.cpp +++ b/src/riffvideo.cpp @@ -380,15 +380,20 @@ void RiffVideo::readMetadata() { xmpData_["Xmp.video.FileSize"] = io_->size(); xmpData_["Xmp.video.MimeType"] = mimeType(); - xmpData_["Xmp.video.Container"] = readStringTag(io_); - - io_->seekOrThrow(io_->tell() + DWORD, BasicIo::beg, ErrorCode::kerFailedToReadImageData); // skeep id + HeaderReader header(io_); + xmpData_["Xmp.video.Container"] = header.getId(); xmpData_["Xmp.video.FileType"] = readStringTag(io_); decodeBlocks(); } // RiffVideo::readMetadata +RiffVideo::HeaderReader::HeaderReader(BasicIo::UniquePtr& io) { + Internal::enforce(io->size() > io->tell() + DWORD + DWORD, Exiv2::ErrorCode::kerCorruptedMetadata); + id_ = readStringTag(io); + size_ = readDWORDTag(io); +} + bool RiffVideo::equal(const std::string& str1, const std::string& str2) { if (str1.size() != str2.size()) return false; @@ -398,64 +403,63 @@ bool RiffVideo::equal(const std::string& str1, const std::string& str2) { return true; } -void RiffVideo::readList(uint64_t size) { +void RiffVideo::readList(HeaderReader& header_) { DataBuf FormTypeBuf_ = io_->read(DWORD); #ifdef EXIV2_DEBUG_MESSAGES - EXV_DEBUG << "-> Reading list : id= " << id << " type= " << Exiv2::toString(FormTypeBuf_.data()) << " size= " << size - << "(" << io_->tell() << "/" << io_->size() << ")" << std::endl; + EXV_DEBUG << "-> Reading list : id= " << header_.getId() << " type= " << Exiv2::toString(FormTypeBuf_.data()) + << " size= " << header_.getSize() << "(" << io_->tell() << "/" << io_->size() << ")" << std::endl; #endif if (equal(Exiv2::toString(FormTypeBuf_.data()), CHUNK_ID_INFO)) - readInfoListChunk(size); + readInfoListChunk(header_.getSize()); else if (equal(Exiv2::toString(FormTypeBuf_.data()), CHUNK_ID_MOVI)) { - readMoviList(size); + readMoviList(header_.getSize()); } } -void RiffVideo::readChunk(uint64_t size, const std::string& id) { +void RiffVideo::readChunk(HeaderReader& header_) { #ifdef EXIV2_DEBUG_MESSAGES - EXV_DEBUG << "--> Reading Chunk : [" << id << "] size= " << size << "(" << io_->tell() << "/" << io_->size() << ")" - << std::endl; + EXV_DEBUG << "--> Reading Chunk : [" << header_.getId() << "] size= " << header_.getSize() << "(" << io_->tell() + << "/" << io_->size() << ")" << std::endl; #endif - if (equal(id, CHUNK_ID_AVIH)) + if (equal(header_.getId(), CHUNK_ID_AVIH)) readAviHeader(); - else if (equal(id, CHUNK_ID_STRH)) + else if (equal(header_.getId(), CHUNK_ID_STRH)) readStreamHeader(); - else if (equal(id, CHUNK_ID_STRF)) - readStreamFormat(size); - else if (equal(id, CHUNK_ID_FMT)) { + else if (equal(header_.getId(), CHUNK_ID_STRF)) + readStreamFormat(header_.getSize()); + else if (equal(header_.getId(), CHUNK_ID_FMT)) { streamType_ = Audio; - readStreamFormat(size); - } else if (equal(id, CHUNK_ID_STRD)) - readStreamData(size); - else if (equal(id, CHUNK_ID_STRN)) - StreamName(size); - else if (equal(id, CHUNK_ID_VPRP)) - readVPRPChunk(size); - else if (equal(id, CHUNK_ID_IDX1)) - readIndexChunk(size); - else if (equal(id, CHUNK_ID_DATA)) - readDataChunk(size); - else if (equal(id, CHUNK_ID_JUNK)) - readJunk(size); + readStreamFormat(header_.getSize()); + } else if (equal(header_.getId(), CHUNK_ID_STRD)) + readStreamData(header_.getSize()); + else if (equal(header_.getId(), CHUNK_ID_STRN)) + StreamName(header_.getSize()); + else if (equal(header_.getId(), CHUNK_ID_VPRP)) + readVPRPChunk(header_.getSize()); + else if (equal(header_.getId(), CHUNK_ID_IDX1)) + readIndexChunk(header_.getSize()); + else if (equal(header_.getId(), CHUNK_ID_DATA)) + readDataChunk(header_.getSize()); + else if (equal(header_.getId(), CHUNK_ID_JUNK)) + readJunk(header_.getSize()); else { #ifdef EXIV2_DEBUG_MESSAGES - EXV_DEBUG << "--> Ignoring Chunk : " << id << "] size= " << size << "(" << io_->tell() << "/" << io_->size() << ")" - << std::endl; + EXV_DEBUG << "--> Ignoring Chunk : " << header_.getId() << "] size= " << header_.getSize() << "(" << io_->tell() + << "/" << io_->size() << ")" << std::endl; #endif - io_->seekOrThrow(io_->tell() + size, BasicIo::beg, ErrorCode::kerFailedToReadImageData); + io_->seekOrThrow(io_->tell() + header_.getSize(), BasicIo::beg, ErrorCode::kerFailedToReadImageData); } } void RiffVideo::decodeBlocks() { - std::string id = readStringTag(io_); - uint64_t size = readDWORDTag(io_); - if (equal(id, CHUNK_ID_LIST)) { - readList(size); + HeaderReader header(io_); + if (equal(header.getId(), CHUNK_ID_LIST)) { + readList(header); } else { - readChunk(size, id); + readChunk(header); } if (!io_->eof() && io_->tell() < io_->size()) {