diff --git a/app/actions.cpp b/app/actions.cpp index 599a9534..439ec289 100644 --- a/app/actions.cpp +++ b/app/actions.cpp @@ -170,8 +170,8 @@ int setModeAndPrintStructure(Exiv2::PrintStructureOption option, const std::stri if (binary && option == Exiv2::kpsIccProfile) { std::stringstream output(std::stringstream::out | std::stringstream::binary); result = printStructure(output, option, path); - if (result == 0) { - std::string str = output.str(); + std::string str = output.str(); + if (result == 0 && !str.empty()) { Exiv2::DataBuf iccProfile(str.size()); Exiv2::DataBuf ascii(str.size() * 3 + 1); ascii.write_uint8(str.size() * 3, 0); @@ -549,9 +549,11 @@ bool Print::printMetadatum(const Exiv2::Metadatum& md, const Exiv2::Image* pImag if (Params::instance().printItems_ & Params::prHex) { if (!first) std::cout << std::endl; - Exiv2::DataBuf buf(md.size()); - md.copy(buf.data(), pImage->byteOrder()); - Exiv2::hexdump(std::cout, buf.c_data(), buf.size()); + if (md.size() > 0) { + Exiv2::DataBuf buf(md.size()); + md.copy(buf.data(), pImage->byteOrder()); + Exiv2::hexdump(std::cout, buf.c_data(), buf.size()); + } } std::cout << std::endl; return true; diff --git a/samples/addmoddel.cpp b/samples/addmoddel.cpp index c91204ae..0ea379d8 100644 --- a/samples/addmoddel.cpp +++ b/samples/addmoddel.cpp @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later + // Sample program showing how to add, modify and delete Exif metadata. #include diff --git a/src/bmffimage.cpp b/src/bmffimage.cpp index a45076c0..977e1be8 100644 --- a/src/bmffimage.cpp +++ b/src/bmffimage.cpp @@ -620,7 +620,7 @@ void BmffImage::printStructure(std::ostream& out, Exiv2::PrintStructureOption op break; // do nothing case kpsIccProfile: { - out.write(iccProfile_.c_str(), iccProfile_.size()); + out.write(iccProfile_.empty() ? nullptr : iccProfile_.c_str(), iccProfile_.size()); } break; #ifdef EXV_HAVE_XMP_TOOLKIT diff --git a/src/crwimage_int.cpp b/src/crwimage_int.cpp index 01a39c55..ebc7e7e8 100644 --- a/src/crwimage_int.cpp +++ b/src/crwimage_int.cpp @@ -853,7 +853,7 @@ void CrwMap::encodeBasic(const Image& image, const CrwMapping* pCrwMapping, Ciff auto ed = image.exifData().findKey(ek); // Set the new value or remove the entry - if (ed != image.exifData().end()) { + if (ed != image.exifData().end() && ed->size() > 0) { DataBuf buf(ed->size()); ed->copy(buf.data(), pHead->byteOrder()); pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, std::move(buf)); diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index a191ff2b..57ce060c 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -184,8 +184,9 @@ void JpegBase::readMetadata() { #ifdef EXIV2_DEBUG_MESSAGES std::cerr << "Found app13 segment, size = " << size << "\n"; #endif - // Append to psBlob - append(psBlob, buf.c_data(16), size - 16); + if (buf.size() > 16) { // Append to psBlob + append(psBlob, buf.c_data(16), size - 16); + } // Check whether psBlob is complete if (!psBlob.empty() && Photoshop::valid(&psBlob[0], psBlob.size())) { --search; @@ -745,9 +746,9 @@ void JpegBase::doWriteMetadata(BasicIo& outIo) { bo = littleEndian; setByteOrder(bo); } - WriteMethod wm = ExifParser::encode(blob, rawExif.c_data(), rawExif.size(), bo, exifData_); - const byte* pExifData = rawExif.c_data(); + const byte* pExifData = rawExif.empty() ? nullptr : rawExif.c_data(); size_t exifSize = rawExif.size(); + WriteMethod wm = ExifParser::encode(blob, pExifData, exifSize, bo, exifData_); if (wm == wmIntrusive) { pExifData = !blob.empty() ? &blob[0] : nullptr; exifSize = blob.size(); @@ -844,7 +845,7 @@ void JpegBase::doWriteMetadata(BasicIo& outIo) { // IPTC block if there is no new IPTC data to write DataBuf newPsData = Photoshop::setIptcIrb(!psBlob.empty() ? psBlob.data() : nullptr, psBlob.size(), iptcData_); const long maxChunkSize = 0xffff - 16; - const byte* chunkStart = newPsData.c_data(); + const byte* chunkStart = newPsData.empty() ? nullptr : newPsData.c_data(); const byte* chunkEnd = newPsData.empty() ? nullptr : newPsData.c_data(newPsData.size() - 1); while (chunkStart < chunkEnd) { // Determine size of next chunk diff --git a/src/pngchunk_int.cpp b/src/pngchunk_int.cpp index 4e18431b..0855db9c 100644 --- a/src/pngchunk_int.cpp +++ b/src/pngchunk_int.cpp @@ -56,7 +56,8 @@ void PngChunk::decodeTXTChunk(Image* pImage, const DataBuf& data, TxtChunkType t #ifdef EXIV2_DEBUG_MESSAGES std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk data: " << std::string(arr.c_str(), arr.size()) << std::endl; #endif - parseChunkContent(pImage, key.c_data(), key.size(), arr); + if (!key.empty()) + parseChunkContent(pImage, key.c_data(), key.size(), arr); } DataBuf PngChunk::decodeTXTChunk(const DataBuf& data, TxtChunkType type) { @@ -558,8 +559,10 @@ DataBuf PngChunk::readRawProfile(const DataBuf& text, bool iTXt) { return {}; } - // Copy profile, skipping white space and column 1 "=" signs + if (info.empty()) // Early return + return info; + // Copy profile, skipping white space and column 1 "=" signs unsigned char* dp = info.data(); // decode pointer size_t nibbles = length * 2; diff --git a/src/pngimage.cpp b/src/pngimage.cpp index c7d274bc..c801bdd7 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -234,8 +234,10 @@ void PngImage::printStructure(std::ostream& out, PrintStructureOption option, in } DataBuf buff(dataOffset); - bufRead = io_->read(buff.data(), dataOffset); - enforce(bufRead == dataOffset, ErrorCode::kerFailedToReadImageData); + if (dataOffset > 0) { + bufRead = io_->read(buff.data(), dataOffset); + enforce(bufRead == dataOffset, ErrorCode::kerFailedToReadImageData); + } io_->seek(restore, BasicIo::beg); // format output @@ -426,7 +428,9 @@ void PngImage::readMetadata() { if (chunkType == "IEND" || chunkType == "IHDR" || chunkType == "tEXt" || chunkType == "zTXt" || chunkType == "eXIf" || chunkType == "iTXt" || chunkType == "iCCP") { DataBuf chunkData(chunkLength); - readChunk(chunkData, *io_); // Extract chunk data. + if (chunkLength > 0) { + readChunk(chunkData, *io_); // Extract chunk data. + } if (chunkType == "IEND") { return; // Last chunk found: we stop parsing. diff --git a/src/rafimage.cpp b/src/rafimage.cpp index f535f99d..0b048c45 100644 --- a/src/rafimage.cpp +++ b/src/rafimage.cpp @@ -259,13 +259,15 @@ void RafImage::readMetadata() { if (io_->seek(jpg_img_off + 12, BasicIo::beg) != 0) throw Error(ErrorCode::kerFailedToReadImageData); - io_->read(buf.data(), buf.size()); - if (io_->error() || io_->eof()) - throw Error(ErrorCode::kerFailedToReadImageData); + if (!buf.empty()) { + io_->read(buf.data(), buf.size()); + if (io_->error() || io_->eof()) + throw Error(ErrorCode::kerFailedToReadImageData); + } - io_->seek(0, BasicIo::beg); // rewind + // io_->seek(0, BasicIo::beg); // rewind - ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.c_data(), buf.size()); + ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.empty() ? nullptr : buf.c_data(), buf.size()); exifData_["Exif.Image2.JPEGInterchangeFormat"] = getULong(jpg_img_offset, bigEndian); exifData_["Exif.Image2.JPEGInterchangeFormatLength"] = getULong(jpg_img_length, bigEndian); diff --git a/src/tiffcomposite_int.cpp b/src/tiffcomposite_int.cpp index af3d6a53..eb1d3c60 100644 --- a/src/tiffcomposite_int.cpp +++ b/src/tiffcomposite_int.cpp @@ -976,7 +976,7 @@ uint32_t TiffDirectory::writeDirEntry(IoWrapper& ioWrapper, ByteOrder byteOrder, uint32_t TiffEntryBase::doWrite(IoWrapper& ioWrapper, ByteOrder byteOrder, int64_t /*offset*/, uint32_t /*valueIdx*/, uint32_t /*dataIdx*/, uint32_t& /*imageIdx*/) { - if (!pValue_) + if (!pValue_ || pValue_->size() == 0) return 0; DataBuf buf(pValue_->size()); @@ -1182,7 +1182,8 @@ uint32_t TiffDataEntry::doWriteData(IoWrapper& ioWrapper, ByteOrder /*byteOrder* return 0; DataBuf buf = pValue()->dataArea(); - ioWrapper.write(buf.c_data(), buf.size()); + if (!buf.empty()) + ioWrapper.write(buf.c_data(), buf.size()); // Align data to word boundary uint32_t align = (buf.size() & 1); if (align) diff --git a/src/webpimage.cpp b/src/webpimage.cpp index 71fdd599..3ed1dbaa 100644 --- a/src/webpimage.cpp +++ b/src/webpimage.cpp @@ -162,10 +162,12 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) { // Check that `size_u32` is safe to cast to `long`. enforce(size_u32 <= std::numeric_limits::max(), Exiv2::ErrorCode::kerCorruptedMetadata); DataBuf payload(size_u32); - io_->readOrThrow(payload.data(), payload.size(), Exiv2::ErrorCode::kerCorruptedMetadata); - if (payload.size() % 2) { - byte c = 0; - io_->readOrThrow(&c, 1, Exiv2::ErrorCode::kerCorruptedMetadata); + if (!payload.empty()) { + io_->readOrThrow(payload.data(), payload.size(), Exiv2::ErrorCode::kerCorruptedMetadata); + if (payload.size() % 2) { + byte c = 0; + io_->readOrThrow(&c, 1, Exiv2::ErrorCode::kerCorruptedMetadata); + } } /* Chunk with information about features @@ -528,7 +530,9 @@ void WebPImage::decodeChunks(long filesize) { DataBuf payload(size); - if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) { + if (payload.empty()) { + io_->seek(size, BasicIo::cur); + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) { enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata); has_canvas_data = true; diff --git a/tests/bugfixes/github/test_issue_960.py b/tests/bugfixes/github/test_issue_960.py index 635ee3f7..ab5e19dc 100644 --- a/tests/bugfixes/github/test_issue_960.py +++ b/tests/bugfixes/github/test_issue_960.py @@ -14,8 +14,7 @@ class WebPImageGetHeaderOffset(metaclass=CaseMeta): commands = ["$exiv2 $filename1"] stdout = [""] stderr = [ -"""Warning: Failed to decode Exif metadata. -Exiv2 exception in print action for file $filename1: +"""Exiv2 exception in print action for file $filename1: $kerCorruptedMetadata """ ]