diff --git a/src/jp2image.cpp b/src/jp2image.cpp index 39a6f581..7c270486 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -446,25 +446,27 @@ namespace Exiv2 } // Jp2Image::readMetadata - void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option,int depth) + void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, int depth) { - if (io_->open() != 0) throw Error(kerDataSourceOpenFailed, io_->path(), strError()); + if (io_->open() != 0) + throw Error(kerDataSourceOpenFailed, io_->path(), strError()); // Ensure that this is the correct image type if (!isJp2Type(*io_, false)) { - if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); + if (io_->error() || io_->eof()) + throw Error(kerFailedToReadImageData); throw Error(kerNotAJpeg); } - bool bPrint = option == kpsBasic || option==kpsRecursive; + bool bPrint = option == kpsBasic || option == kpsRecursive; bool bRecursive = option == kpsRecursive; - bool bICC = option == kpsIccProfile; - bool bXMP = option == kpsXMP; + bool bICC = option == kpsIccProfile; + bool bXMP = option == kpsXMP; bool bIPTCErase = option == kpsIptcErase; - if ( bPrint ) { + if (bPrint) { out << "STRUCTURE OF JPEG2000 FILE: " << io_->path() << std::endl; - out << " address | length | box | data" << std::endl ; + out << " address | length | box | data" << std::endl; } if ( bPrint || bXMP || bICC || bIPTCErase ) { @@ -479,122 +481,127 @@ namespace Exiv2 { position = io_->tell(); box.length = getLong((byte*)&box.length, bigEndian); - box.type = getLong((byte*)&box.type, bigEndian); - - if ( bPrint ) { - out << Internal::stringFormat("%8ld | %8ld | ",(size_t)(position-sizeof(box)),(size_t) box.length) << toAscii(box.type) << " | " ; - bLF = true ; - if ( box.type == kJp2BoxTypeClose ) lf(out,bLF); + box.type = getLong((byte*)&box.type, bigEndian); + + if (bPrint) { + out << Internal::stringFormat("%8ld | %8ld | ", (size_t)(position - sizeof(box)), + (size_t)box.length) + << toAscii(box.type) << " | "; + bLF = true; + if (box.type == kJp2BoxTypeClose) + lf(out, bLF); } - if ( box.type == kJp2BoxTypeClose ) break; + if (box.type == kJp2BoxTypeClose) + break; - switch(box.type) - { - case kJp2BoxTypeJp2Header: - { - lf(out,bLF); + switch (box.type) { + case kJp2BoxTypeJp2Header: { + lf(out, bLF); - while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) - && io_->tell() < position + (long) box.length) // don't read beyond the box! + while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) && + io_->tell() < position + (long)box.length) // don't read beyond the box! { int address = io_->tell() - sizeof(subBox); subBox.length = getLong((byte*)&subBox.length, bigEndian); - subBox.type = getLong((byte*)&subBox.type, bigEndian); + subBox.type = getLong((byte*)&subBox.type, bigEndian); - // subBox.length makes no sense if it is larger than the rest of the file - if (subBox.length > io_->size() - io_->tell()) { + if (subBox.length < sizeof(box) || subBox.length > io_->size() - io_->tell()) { throw Error(kerCorruptedMetadata); } - DataBuf data(subBox.length-sizeof(box)); - io_->read(data.pData_,data.size_); - if ( bPrint ) { - out << Internal::stringFormat("%8ld | %8ld | sub:",(size_t)address,(size_t)subBox.length) - << toAscii(subBox.type) - <<" | " << Internal::binaryToString(makeSlice(data, 0, 30)); + + DataBuf data(subBox.length - sizeof(box)); + io_->read(data.pData_, data.size_); + if (bPrint) { + out << Internal::stringFormat("%8ld | %8ld | sub:", (size_t)address, + (size_t)subBox.length) + << toAscii(subBox.type) << " | " + << Internal::binaryToString(makeSlice(data, 0, 30)); bLF = true; } - if(subBox.type == kJp2BoxTypeColorHeader) - { - long pad = 3 ; // don't know why there are 3 padding bytes - if ( bPrint ) { - out << " | pad:" ; - for ( int i = 0 ; i < 3 ; i++ ) out<< " " << (int) data.pData_[i]; + if (subBox.type == kJp2BoxTypeColorHeader) { + long pad = 3; // don't know why there are 3 padding bytes + if (bPrint) { + out << " | pad:"; + for (int i = 0; i < 3; i++) + out << " " << (int)data.pData_[i]; } - long iccLength = getULong(data.pData_+pad, bigEndian); - if ( bPrint ) { - out << " | iccLength:" << iccLength ; + long iccLength = getULong(data.pData_ + pad, bigEndian); + if (bPrint) { + out << " | iccLength:" << iccLength; } - if ( bICC ) { - out.write((const char*)data.pData_+pad,iccLength); + if (bICC) { + out.write((const char*)data.pData_ + pad, iccLength); } } - lf(out,bLF); + lf(out, bLF); } } break; - case kJp2BoxTypeUuid: - { - - if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid)) - { - bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0; - bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; - bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0; - - bool bUnknown= ! (bIsExif || bIsIPTC || bIsXMP); - - if ( bPrint ) { - if ( bIsExif ) out << "Exif: " ; - if ( bIsIPTC ) out << "IPTC: " ; - if ( bIsXMP ) out << "XMP : " ; - if ( bUnknown) out << "????: " ; + case kJp2BoxTypeUuid: { + if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid)) { + bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid)) == 0; + bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid)) == 0; + bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp, sizeof(uuid)) == 0; + + bool bUnknown = !(bIsExif || bIsIPTC || bIsXMP); + + if (bPrint) { + if (bIsExif) + out << "Exif: "; + if (bIsIPTC) + out << "IPTC: "; + if (bIsXMP) + out << "XMP : "; + if (bUnknown) + out << "????: "; } DataBuf rawData; - rawData.alloc(box.length-sizeof(uuid)-sizeof(box)); - long bufRead = io_->read(rawData.pData_, rawData.size_); - if (io_->error()) throw Error(kerFailedToReadImageData); - if (bufRead != rawData.size_) throw Error(kerInputDataReadFailed); - - if ( bPrint ){ - out << Internal::binaryToString(makeSlice(rawData,0,40)); + rawData.alloc(box.length - sizeof(uuid) - sizeof(box)); + long bufRead = io_->read(rawData.pData_, rawData.size_); + if (io_->error()) + throw Error(kerFailedToReadImageData); + if (bufRead != rawData.size_) + throw Error(kerInputDataReadFailed); + + if (bPrint) { + out << Internal::binaryToString(makeSlice(rawData, 0, 40)); out.flush(); } - lf(out,bLF); + lf(out, bLF); - if(bIsExif && bRecursive && rawData.size_ > 0) - { - if ( (rawData.pData_[0] == rawData.pData_[1]) - && (rawData.pData_[0]=='I' || rawData.pData_[0]=='M' ) - ) { - BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_,rawData.size_)); - printTiffStructure(*p,out,option,depth); + if (bIsExif && bRecursive && rawData.size_ > 0) { + if ((rawData.pData_[0] == rawData.pData_[1]) && + (rawData.pData_[0] == 'I' || rawData.pData_[0] == 'M')) { + BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_, rawData.size_)); + printTiffStructure(*p, out, option, depth); } } - if(bIsIPTC && bRecursive) - { + if (bIsIPTC && bRecursive) { IptcData::printStructure(out, makeSlice(rawData.pData_, 0, rawData.size_), depth); } - if( bIsXMP && bXMP ) - { - out.write((const char*)rawData.pData_,rawData.size_); + if (bIsXMP && bXMP) { + out.write((const char*)rawData.pData_, rawData.size_); } } } break; - default: break; + default: + break; } // Move to the next box. io_->seek(static_cast(position - sizeof(box) + box.length), BasicIo::beg); - if (io_->error()) throw Error(kerFailedToReadImageData); - if ( bPrint ) lf(out,bLF); + if (io_->error()) + throw Error(kerFailedToReadImageData); + if (bPrint) + lf(out, bLF); } } - } // JpegBase::printStructure + } // JpegBase::printStructure void Jp2Image::writeMetadata() { diff --git a/test/data/issue_742_poc b/test/data/issue_742_poc new file mode 100644 index 00000000..6b5eb689 Binary files /dev/null and b/test/data/issue_742_poc differ diff --git a/tests/bugfixes/github/test_issue_742.py b/tests/bugfixes/github/test_issue_742.py new file mode 100644 index 00000000..363e616b --- /dev/null +++ b/tests/bugfixes/github/test_issue_742.py @@ -0,0 +1,14 @@ +import system_tests + + +class ThrowsWhenSubBoxLengthIsNotGood(metaclass=system_tests.CaseMeta): + + url = "https://github.com/Exiv2/exiv2/issues/742" + + filename = system_tests.path("$data_path/issue_742_poc") + commands = ["$exiv2 -pX $filename"] + stdout = [""] + stderr = ["""$exiv2_exception_message $filename: +$kerCorruptedMetadata +"""] + retval = [1]