Merge pull request #764 from Exiv2/mergify/bp/0.27-maintenance/pr-753

Automatic backport of pull request #753
v0.27.3
Luis Díaz Más 6 years ago committed by GitHub
commit f33ef06a88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -446,25 +446,27 @@ namespace Exiv2
} // Jp2Image::readMetadata } // 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 // Ensure that this is the correct image type
if (!isJp2Type(*io_, false)) { if (!isJp2Type(*io_, false)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
throw Error(kerNotAJpeg); throw Error(kerNotAJpeg);
} }
bool bPrint = option == kpsBasic || option==kpsRecursive; bool bPrint = option == kpsBasic || option == kpsRecursive;
bool bRecursive = option == kpsRecursive; bool bRecursive = option == kpsRecursive;
bool bICC = option == kpsIccProfile; bool bICC = option == kpsIccProfile;
bool bXMP = option == kpsXMP; bool bXMP = option == kpsXMP;
bool bIPTCErase = option == kpsIptcErase; bool bIPTCErase = option == kpsIptcErase;
if ( bPrint ) { if (bPrint) {
out << "STRUCTURE OF JPEG2000 FILE: " << io_->path() << std::endl; 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 ) { if ( bPrint || bXMP || bICC || bIPTCErase ) {
@ -479,122 +481,127 @@ namespace Exiv2
{ {
position = io_->tell(); position = io_->tell();
box.length = getLong((byte*)&box.length, bigEndian); box.length = getLong((byte*)&box.length, bigEndian);
box.type = getLong((byte*)&box.type, bigEndian); box.type = getLong((byte*)&box.type, bigEndian);
if ( bPrint ) { if (bPrint) {
out << Internal::stringFormat("%8ld | %8ld | ",(size_t)(position-sizeof(box)),(size_t) box.length) << toAscii(box.type) << " | " ; out << Internal::stringFormat("%8ld | %8ld | ", (size_t)(position - sizeof(box)),
bLF = true ; (size_t)box.length)
if ( box.type == kJp2BoxTypeClose ) lf(out,bLF); << 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) switch (box.type) {
{ case kJp2BoxTypeJp2Header: {
case kJp2BoxTypeJp2Header: lf(out, bLF);
{
lf(out,bLF);
while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) &&
&& io_->tell() < position + (long) box.length) // don't read beyond the box! io_->tell() < position + (long)box.length) // don't read beyond the box!
{ {
int address = io_->tell() - sizeof(subBox); int address = io_->tell() - sizeof(subBox);
subBox.length = getLong((byte*)&subBox.length, bigEndian); 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 < sizeof(box) || subBox.length > io_->size() - io_->tell()) {
if (subBox.length > io_->size() - io_->tell()) {
throw Error(kerCorruptedMetadata); throw Error(kerCorruptedMetadata);
} }
DataBuf data(subBox.length-sizeof(box));
io_->read(data.pData_,data.size_); DataBuf data(subBox.length - sizeof(box));
if ( bPrint ) { io_->read(data.pData_, data.size_);
out << Internal::stringFormat("%8ld | %8ld | sub:",(size_t)address,(size_t)subBox.length) if (bPrint) {
<< toAscii(subBox.type) out << Internal::stringFormat("%8ld | %8ld | sub:", (size_t)address,
<<" | " << Internal::binaryToString(makeSlice(data, 0, 30)); (size_t)subBox.length)
<< toAscii(subBox.type) << " | "
<< Internal::binaryToString(makeSlice(data, 0, 30));
bLF = true; bLF = true;
} }
if(subBox.type == kJp2BoxTypeColorHeader) if (subBox.type == kJp2BoxTypeColorHeader) {
{ long pad = 3; // don't know why there are 3 padding bytes
long pad = 3 ; // don't know why there are 3 padding bytes if (bPrint) {
if ( bPrint ) { out << " | pad:";
out << " | pad:" ; for (int i = 0; i < 3; i++)
for ( int i = 0 ; i < 3 ; i++ ) out<< " " << (int) data.pData_[i]; out << " " << (int)data.pData_[i];
} }
long iccLength = getULong(data.pData_+pad, bigEndian); long iccLength = getULong(data.pData_ + pad, bigEndian);
if ( bPrint ) { if (bPrint) {
out << " | iccLength:" << iccLength ; out << " | iccLength:" << iccLength;
} }
if ( bICC ) { if (bICC) {
out.write((const char*)data.pData_+pad,iccLength); out.write((const char*)data.pData_ + pad, iccLength);
} }
} }
lf(out,bLF); lf(out, bLF);
} }
} break; } break;
case kJp2BoxTypeUuid: case kJp2BoxTypeUuid: {
{ if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid)) {
bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid)) == 0;
if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid)) bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid)) == 0;
{ bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp, sizeof(uuid)) == 0;
bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0;
bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; bool bUnknown = !(bIsExif || bIsIPTC || bIsXMP);
bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0;
if (bPrint) {
bool bUnknown= ! (bIsExif || bIsIPTC || bIsXMP); if (bIsExif)
out << "Exif: ";
if ( bPrint ) { if (bIsIPTC)
if ( bIsExif ) out << "Exif: " ; out << "IPTC: ";
if ( bIsIPTC ) out << "IPTC: " ; if (bIsXMP)
if ( bIsXMP ) out << "XMP : " ; out << "XMP : ";
if ( bUnknown) out << "????: " ; if (bUnknown)
out << "????: ";
} }
DataBuf rawData; DataBuf rawData;
rawData.alloc(box.length-sizeof(uuid)-sizeof(box)); rawData.alloc(box.length - sizeof(uuid) - sizeof(box));
long bufRead = io_->read(rawData.pData_, rawData.size_); long bufRead = io_->read(rawData.pData_, rawData.size_);
if (io_->error()) throw Error(kerFailedToReadImageData); if (io_->error())
if (bufRead != rawData.size_) throw Error(kerInputDataReadFailed); throw Error(kerFailedToReadImageData);
if (bufRead != rawData.size_)
if ( bPrint ){ throw Error(kerInputDataReadFailed);
out << Internal::binaryToString(makeSlice(rawData,0,40));
if (bPrint) {
out << Internal::binaryToString(makeSlice(rawData, 0, 40));
out.flush(); out.flush();
} }
lf(out,bLF); lf(out, bLF);
if(bIsExif && bRecursive && rawData.size_ > 0) if (bIsExif && bRecursive && rawData.size_ > 0) {
{ if ((rawData.pData_[0] == rawData.pData_[1]) &&
if ( (rawData.pData_[0] == rawData.pData_[1]) (rawData.pData_[0] == 'I' || rawData.pData_[0] == 'M')) {
&& (rawData.pData_[0]=='I' || rawData.pData_[0]=='M' ) BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_, rawData.size_));
) { printTiffStructure(*p, out, option, depth);
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); IptcData::printStructure(out, makeSlice(rawData.pData_, 0, rawData.size_), depth);
} }
if( bIsXMP && bXMP ) if (bIsXMP && bXMP) {
{ out.write((const char*)rawData.pData_, rawData.size_);
out.write((const char*)rawData.pData_,rawData.size_);
} }
} }
} break; } break;
default: break; default:
break;
} }
// Move to the next box. // Move to the next box.
io_->seek(static_cast<long>(position - sizeof(box) + box.length), BasicIo::beg); io_->seek(static_cast<long>(position - sizeof(box) + box.length), BasicIo::beg);
if (io_->error()) throw Error(kerFailedToReadImageData); if (io_->error())
if ( bPrint ) lf(out,bLF); throw Error(kerFailedToReadImageData);
if (bPrint)
lf(out, bLF);
} }
} }
} // JpegBase::printStructure } // JpegBase::printStructure
void Jp2Image::writeMetadata() void Jp2Image::writeMetadata()
{ {

Binary file not shown.

@ -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]
Loading…
Cancel
Save