diff options
27 files changed, 321 insertions, 132 deletions
diff --git a/XMPCore/source/XMPUtils-FileInfo.cpp b/XMPCore/source/XMPUtils-FileInfo.cpp index 9b0ab53..a2a9f99 100644 --- a/XMPCore/source/XMPUtils-FileInfo.cpp +++ b/XMPCore/source/XMPUtils-FileInfo.cpp @@ -784,9 +784,12 @@ AppendSubtree ( const XMP_Node * sourceNode, XMP_Node * destParent, for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim && destNode!= NULL; ++sourceNum ) { const XMP_Node * sourceField = sourceNode->children[sourceNum]; AppendSubtree ( sourceField, destNode, mergeCompound, replaceOld, deleteEmpty ); - if ( deleteEmpty && destNode->children.empty() ) { - delete ( destNode ); - destParent->children.erase ( destPos ); + + if (deleteEmpty && destNode->children.empty()) + { + delete (destNode); + destNode = NULL; + destParent->children.erase(destPos); } } diff --git a/XMPFiles/source/FileHandlers/FLV_Handler.cpp b/XMPFiles/source/FileHandlers/FLV_Handler.cpp index 84ab95d..8581df4 100644 --- a/XMPFiles/source/FileHandlers/FLV_Handler.cpp +++ b/XMPFiles/source/FileHandlers/FLV_Handler.cpp @@ -212,6 +212,8 @@ static void GetTagInfo ( XMP_IO* fileRef, XMP_Uns64 tagPos, TagInfo * info ) static XMP_Uns32 GetASValueLen ( const XMP_Uns8 * asValue, const XMP_Uns8 * asLimit ) { + if (asValue > asLimit) + return 0; XMP_Uns32 valueLen = 0; const XMP_Uns8 * itemPtr; XMP_Uns32 arrayCount; diff --git a/XMPFiles/source/FileHandlers/P2_Handler.cpp b/XMPFiles/source/FileHandlers/P2_Handler.cpp index 6479caf..d4e6190 100644 --- a/XMPFiles/source/FileHandlers/P2_Handler.cpp +++ b/XMPFiles/source/FileHandlers/P2_Handler.cpp @@ -1138,6 +1138,7 @@ void P2_MetaHandler::ProcessXMP() XML_NodePtr legacyContext, clipMetadata, legacyProp; if ( ! this->p2ClipManager.IsValidP2() ) return; P2_Clip* p2Clip=this->p2ClipManager.GetManagedClip(); + if( p2Clip->GetP2RootNode() == 0) return; XMP_StringPtr p2NS = p2Clip->GetP2RootNode()->ns.c_str(); std::string oldDigest, newDigest; bool digestFound = this->xmpObj.GetStructField ( kXMP_NS_XMP, "NativeDigests", kXMP_NS_XMP, "P2", &oldDigest, 0 ); @@ -1308,24 +1309,27 @@ void P2_MetaHandler::UpdateFile ( bool doSafeUpdate ) if (frameFormat == "50Timecode" || frameFormat == "5994DropTimecode" || frameFormat == "5994NonDropTimecode") { p2Clip = this->p2ClipManager.GetManagedClip(); - XMP_StringPtr p2NS = p2Clip->GetP2RootNode()->ns.c_str(); - XML_NodePtr legacyVideoContext = p2Clip->GetEssenceListNode(); - if (legacyVideoContext != 0) + if( p2Clip->GetP2RootNode() != 0 ) { - legacyVideoContext = legacyVideoContext->GetNamedElement(p2NS, "Video"); - XML_NodePtr legacyProp = legacyVideoContext->GetNamedElement(p2NS, "StartTimecode"); - if ((legacyProp != 0) && legacyProp->IsLeafContentNode()) - { - AdjustTimeCode( xmpStartTimeCode, true ); - if (xmpStartTimeCode != legacyProp->GetLeafContentValue()) - { - legacyProp->SetLeafContentValue(xmpStartTimeCode.c_str()); - updateLegacyXML = true; - } - } - } - } - } + XMP_StringPtr p2NS = p2Clip->GetP2RootNode()->ns.c_str(); + XML_NodePtr legacyVideoContext = p2Clip->GetEssenceListNode(); + if (legacyVideoContext != 0) + { + legacyVideoContext = legacyVideoContext->GetNamedElement(p2NS, "Video"); + XML_NodePtr legacyProp = legacyVideoContext->GetNamedElement(p2NS, "StartTimecode"); + if ((legacyProp != 0) && legacyProp->IsLeafContentNode()) + { + AdjustTimeCode( xmpStartTimeCode, true ); + if (xmpStartTimeCode != legacyProp->GetLeafContentValue()) + { + legacyProp->SetLeafContentValue(xmpStartTimeCode.c_str()); + updateLegacyXML = true; + } + } + } + } + } + } std::string newDigest; this->p2ClipManager.GetManagedClip()->CreateDigest ( &newDigest ); diff --git a/XMPFiles/source/FileHandlers/PSD_Handler.cpp b/XMPFiles/source/FileHandlers/PSD_Handler.cpp index e910073..e17a65a 100644 --- a/XMPFiles/source/FileHandlers/PSD_Handler.cpp +++ b/XMPFiles/source/FileHandlers/PSD_Handler.cpp @@ -142,7 +142,13 @@ void PSD_MetaHandler::CacheFileData() cmLen = GetUns32BE ( &psdHeader[26] ); - XMP_Int64 psirOrigin = 26 + 4 + cmLen; + XMP_Int64 psirOrigin = 26 + 4 + static_cast<XMP_Int64>(cmLen); + XMP_Int64 fileLength = fileRef->Length(); + + if (psirOrigin > fileLength) + { + XMP_Throw("Invalid PSD chunk length", kXMPErr_BadPSD); + } filePos = fileRef->Seek ( psirOrigin, kXMP_SeekFromStart ); if ( filePos != psirOrigin ) return; // Throw? @@ -153,7 +159,9 @@ void PSD_MetaHandler::CacheFileData() this->psirMgr.ParseFileResources ( fileRef, psirLen ); PSIR_Manager::ImgRsrcInfo xmpInfo; - bool found = this->psirMgr.GetImgRsrc ( kPSIR_XMP, &xmpInfo ); + bool found = this->psirMgr.GetImgRsrc(kPSIR_XMP, &xmpInfo); + if (psirLen < xmpInfo.dataLen) + return; if ( found ) { @@ -427,4 +435,4 @@ void PSD_MetaHandler::WriteTempFile ( XMP_IO* tempRef ) } // PSD_MetaHandler::WriteTempFile -// ================================================================================================= +// =================================================================================================
\ No newline at end of file diff --git a/XMPFiles/source/FileHandlers/SWF_Handler.cpp b/XMPFiles/source/FileHandlers/SWF_Handler.cpp index 9a7443f..8ca52de 100644 --- a/XMPFiles/source/FileHandlers/SWF_Handler.cpp +++ b/XMPFiles/source/FileHandlers/SWF_Handler.cpp @@ -141,6 +141,7 @@ void SWF_MetaHandler::CacheFileData() { // Look for the FileAttributes and Metadata tags. + if(this->expandedSize <= SWF_IO::HeaderPrefixSize ) return; // Throw? this->firstTagOffset = SWF_IO::FileHeaderSize ( this->expandedSWF[SWF_IO::HeaderPrefixSize] ); XMP_Uns32 currOffset = this->firstTagOffset; @@ -237,6 +238,9 @@ void SWF_MetaHandler::UpdateFile ( bool doSafeUpdate ) PutUns16LE ( ((SWF_IO::FileAttributesTagID << 6) | 4), &buffer[0] ); PutUns32LE ( SWF_IO::HasMetadataMask, &buffer[2] ); + if(this->expandedSWF.size() < this->firstTagOffset ){ + XMP_Throw ( "Index not valid.Invalid SWF, can't update.", kXMPErr_BadIndex ); + } this->expandedSWF.insert ( (this->expandedSWF.begin() + this->firstTagOffset), 6, 0 ); memcpy ( &this->expandedSWF[this->firstTagOffset], &buffer[0], 6 ); @@ -270,6 +274,9 @@ void SWF_MetaHandler::UpdateFile ( bool doSafeUpdate ) this->metadataTag.tagOffset += attrTagLength; // The FileAttributes tag will become in front. } + if(this->expandedSWF.size() < this->firstTagOffset ){ + XMP_Throw ( "Index not valid.Invalid SWF, can't update.", kXMPErr_BadIndex ); + } this->expandedSWF.insert ( (this->expandedSWF.begin() + this->firstTagOffset), attrTagLength, 0 ); memcpy ( &this->expandedSWF[this->firstTagOffset], &attrTag[0], attrTagLength ); @@ -300,6 +307,9 @@ void SWF_MetaHandler::UpdateFile ( bool doSafeUpdate ) this->metadataTag.contentLength = (XMP_Uns32)this->xmpPacket.size(); XMP_Uns32 newMetaLength = 6 + this->metadataTag.contentLength; // Always use a long tag header. + if(this->expandedSWF.size() < this->metadataTag.tagOffset ){ + XMP_Throw ( "Index not valid.Invalid SWF, can't update.", kXMPErr_BadIndex ); + } this->expandedSWF.insert ( (this->expandedSWF.begin() + this->metadataTag.tagOffset), newMetaLength, 0 ); PutUns16LE ( ((SWF_IO::MetadataTagID << 6) | SWF_IO::TagLengthMask), &this->expandedSWF[this->metadataTag.tagOffset] ); diff --git a/XMPFiles/source/FileHandlers/TIFF_Handler.cpp b/XMPFiles/source/FileHandlers/TIFF_Handler.cpp index 98b3e65..bea3a8c 100644 --- a/XMPFiles/source/FileHandlers/TIFF_Handler.cpp +++ b/XMPFiles/source/FileHandlers/TIFF_Handler.cpp @@ -238,7 +238,7 @@ void TIFF_MetaHandler::ProcessXMP() iptcDigestState = PhotoDataUtils::CheckIPTCDigest ( iptcInfo.dataPtr, iptcInfo.dataLen, digestInfo.dataPtr ); - if ( (iptcDigestState == kDigestDiffers) && (kTIFF_TypeSizes[iptcInfo.type] > 1) ) { + if ( (iptcDigestState == kDigestDiffers) && (kTIFF_TypeSizes[iptcInfo.type] > 1) && iptcInfo.dataLen > 0) { XMP_Uns8 * endPtr = (XMP_Uns8*)iptcInfo.dataPtr + iptcInfo.dataLen - 1; XMP_Uns8 * minPtr = endPtr - kTIFF_TypeSizes[iptcInfo.type] + 1; while ( (endPtr >= minPtr) && (*endPtr == 0) ) --endPtr; diff --git a/XMPFiles/source/FileHandlers/UCF_Handler.cpp b/XMPFiles/source/FileHandlers/UCF_Handler.cpp index 8063ed8..ee03e24 100644 --- a/XMPFiles/source/FileHandlers/UCF_Handler.cpp +++ b/XMPFiles/source/FileHandlers/UCF_Handler.cpp @@ -490,6 +490,9 @@ void UCF_MetaHandler::CacheFileData() } have = CHUNK - strm.avail_out; + if ((bytesWritten + have) > sizeUncompressed){ + XMP_Throw("UCF Bad XMP block", kXMPErr_BadBlockFormat); + } memcpy( (unsigned char*) packetStr + bytesWritten , out , have ); bytesWritten += have; @@ -551,7 +554,6 @@ void UCF_MetaHandler::UpdateFile ( bool doSafeUpdate ) uncomprPacketLen = (XMP_StringLen) xmpPacket.size(); finalPacketStr = uncomprPacketStr; // will be overriden if compressedXMP==true finalPacketLen = uncomprPacketLen; - std::string compressedPacket; // moot if non-compressed, still here for scope reasons (having to keep a .c_str() alive) if ( !x ) // if new XMP... { @@ -588,6 +590,9 @@ void UCF_MetaHandler::UpdateFile ( bool doSafeUpdate ) unsigned int have; z_stream strm; unsigned char out[CHUNK]; + /* initilalisation for fix to CTECHXMP-4170441*/ + strm.total_out = 0; + strm.total_in = 0; /* allocate deflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; diff --git a/XMPFiles/source/FileHandlers/UCF_Handler.hpp b/XMPFiles/source/FileHandlers/UCF_Handler.hpp index 54a1a11..0177112 100644 --- a/XMPFiles/source/FileHandlers/UCF_Handler.hpp +++ b/XMPFiles/source/FileHandlers/UCF_Handler.hpp @@ -711,6 +711,7 @@ private: XMP_StringLen uncomprPacketLen; XMP_StringPtr finalPacketStr; XMP_StringLen finalPacketLen; + std::string compressedPacket; std::vector<CDFileHeader> cdEntries; EndOfCD endOfCD; void writeOut( XMP_IO* sourceFile, XMP_IO* targetFile, bool isRewrite, bool isInPlace); diff --git a/XMPFiles/source/FormatSupport/ASF_Support.cpp b/XMPFiles/source/FormatSupport/ASF_Support.cpp index 1427dfe..a6a0fef 100644 --- a/XMPFiles/source/FormatSupport/ASF_Support.cpp +++ b/XMPFiles/source/FormatSupport/ASF_Support.cpp @@ -150,7 +150,8 @@ bool ASF_Support::ReadHeaderObject ( XMP_IO* fileRef, ObjectState& inOutObjectSt XMP_Uns32 numberOfHeaders = GetUns32LE ( &buffer[24] ); ASF_ObjectBase objectBase; - while ( read < newObject.len ) { + while (read < newObject.len && numberOfHeaders > 0) + { fileRef->Seek ( pos, kXMP_SeekFromStart ); if ( kASF_ObjectBaseLen != fileRef->Read ( &objectBase, kASF_ObjectBaseLen, true ) ) break; @@ -228,7 +229,7 @@ bool ASF_Support::ReadHeaderObject ( XMP_IO* fileRef, ObjectState& inOutObjectSt XMP_Uns32 fieldPos = 28; // copyright URL is 3. element with variable size - for ( int i = 1; i <= 3 ; ++i ) { + for ( int i = 1; i <= 3 && fieldPos < buffer.size() ; ++i ) { XMP_Uns32 len = GetUns32LE ( &buffer[fieldPos] ); if ( i == 3 ) { std::string copyrightURLStr = buffer.substr ( fieldPos + 4, len ); @@ -276,8 +277,8 @@ bool ASF_Support::ReadHeaderObject ( XMP_IO* fileRef, ObjectState& inOutObjectSt pos += objectBase.size; read += objectBase.size; + numberOfHeaders--; } - } catch ( ... ) { return false; @@ -328,7 +329,7 @@ bool ASF_Support::WriteHeaderObject ( XMP_IO* sourceRef, XMP_IO* destRef, const header.append ( buffer.c_str(), bufferSize ); - while ( read < object.len ) { + while ( read < object.len && numberOfHeaders > 0 ) { sourceRef->Seek ( pos, kXMP_SeekFromStart ); if ( kASF_ObjectBaseLen != sourceRef->Read ( &objectBase, kASF_ObjectBaseLen, true ) ) break; @@ -503,7 +504,7 @@ bool ASF_Support::WriteHeaderObject ( XMP_IO* sourceRef, XMP_IO* destRef, const pos += objectBase.size; read += objectBase.size; - + numberOfHeaders--; writtenObjects ++; } diff --git a/XMPFiles/source/FormatSupport/ID3_Support.cpp b/XMPFiles/source/FormatSupport/ID3_Support.cpp index 3a9c4ad..6ada5a3 100644 --- a/XMPFiles/source/FormatSupport/ID3_Support.cpp +++ b/XMPFiles/source/FormatSupport/ID3_Support.cpp @@ -442,7 +442,7 @@ ID3v2Frame::ID3v2Frame ( XMP_Uns32 _id ) : frameDefaults void ID3v2Frame::release() { - if ( this->content != 0 ) delete this->content; + if ( this->content != 0 ) delete [] content; this->content = 0; this->contentSize = 0; } diff --git a/XMPFiles/source/FormatSupport/P2_Support.cpp b/XMPFiles/source/FormatSupport/P2_Support.cpp index dc65c3d..be6242f 100644 --- a/XMPFiles/source/FormatSupport/P2_Support.cpp +++ b/XMPFiles/source/FormatSupport/P2_Support.cpp @@ -122,7 +122,10 @@ void P2_Clip::CacheClipContent() { if (headContentCached) return; headContentCached = true; - XMP_StringPtr p2NameSpace=GetP2RootNode()->ns.c_str(); + XML_NodePtr p2RootNode = GetP2RootNode(); + if( p2RootNode == 0 ) return; + XMP_StringPtr p2NameSpace = p2RootNode->ns.c_str(); + p2ClipContent = GetP2RootNode()->GetNamedElement ( p2NameSpace, "ClipContent" ); if ( p2ClipContent == 0 ) return; XML_NodePtr p2node; @@ -377,7 +380,9 @@ void P2_SpannedClip::CreateDigest ( std::string * digestStr ) digestStr->erase(); if ( this->headContent.clipMetadata == 0 ) return; // Bail if we don't have any legacy XML. - XMP_StringPtr p2NS = this->GetP2RootNode()->ns.c_str(); + XML_NodePtr p2RootNode = this->GetP2RootNode(); // Return if there is no root node. + if( p2RootNode == 0 ) return; + XMP_StringPtr p2NS = p2RootNode->ns.c_str(); XML_NodePtr legacyContext; MD5_CTX md5Context; unsigned char digestBin [16]; diff --git a/XMPFiles/source/FormatSupport/PNG_Support.cpp b/XMPFiles/source/FormatSupport/PNG_Support.cpp index f604253..42d523c 100644 --- a/XMPFiles/source/FormatSupport/PNG_Support.cpp +++ b/XMPFiles/source/FormatSupport/PNG_Support.cpp @@ -249,7 +249,7 @@ namespace PNG_Support } //skip the current chunk. - inOutPosition += 8 + chunkLength + CRC; + inOutPosition += 8 + static_cast<XMP_Int64>(chunkLength) + CRC; if(inOutPosition > fileLength) { diff --git a/XMPFiles/source/FormatSupport/PostScript_Support.cpp b/XMPFiles/source/FormatSupport/PostScript_Support.cpp index e455aec..d958880 100644 --- a/XMPFiles/source/FormatSupport/PostScript_Support.cpp +++ b/XMPFiles/source/FormatSupport/PostScript_Support.cpp @@ -1015,7 +1015,7 @@ std::string PostScript_Support::ConvertToDate(const char* inString) if(itr!=tokenzs.end()) { ++itr; - if (itr!=tokenzs.end()&&itr->noOfDelimiter==0 && IsNumeric(itr->token[0]) ) + if (itr<tokenzs.end() && itr->noOfDelimiter==0 && IsNumeric(itr->token[0]) ) { const char * str=itr->token.c_str(); short day= GetNumber(&str); @@ -1024,6 +1024,10 @@ std::string PostScript_Support::ConvertToDate(const char* inString) date.day=day; } } + else if (itr == tokenzs.end()) + { + break; + } } } } diff --git a/XMPFiles/source/FormatSupport/RIFF.cpp b/XMPFiles/source/FormatSupport/RIFF.cpp index a4e7e05..8cd76ca 100644 --- a/XMPFiles/source/FormatSupport/RIFF.cpp +++ b/XMPFiles/source/FormatSupport/RIFF.cpp @@ -186,6 +186,10 @@ Chunk::Chunk( ContainerChunk* _parent, RIFF_MetaHandler* handler, bool skip, Chu bool repairFile = XMP_OptionIsSet ( handler->parent->openFlags, kXMPFiles_OpenRepairFile ); if ( (! isUpdate) || (repairFile && (_parent == 0)) ) { this->oldSize = chunkLimit - this->oldPos; + if (this->oldSize < 8) + { + XMP_Throw("Invalid RIFF chunk size", kXMPErr_BadFileFormat); + } } else { XMP_Throw ( "Bad RIFF chunk size", kXMPErr_BadFileFormat ); } diff --git a/XMPFiles/source/FormatSupport/ReconcileLegacy.hpp b/XMPFiles/source/FormatSupport/ReconcileLegacy.hpp index f124a6f..8805dce 100644 --- a/XMPFiles/source/FormatSupport/ReconcileLegacy.hpp +++ b/XMPFiles/source/FormatSupport/ReconcileLegacy.hpp @@ -87,7 +87,7 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // Here are the primary (0th) IFD tags that get special treatment: // // 270, 33432 - ASCII mapped to alt-text['x-default'] -// 306 - DateTime master +// 306 - DateTime main // 315 - ASCII mapped to text seq[1] // // Here are the primary (0th) IFD tags that get mapped by type and count: @@ -99,7 +99,7 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // // 34856, 41484 - OECF/SFR table // 36864, 40960 - 4 ASCII chars to text -// 36867, 36868 - DateTime master +// 36867, 36868 - DateTime main // 37121 - 4 UInt8 to integer seq // 37385 - Flash struct // 37510 - explicitly encoded text to alt-text['x-default'] @@ -116,8 +116,8 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // Here are the GPS IFD tags that get special treatment: // // 0 - 4 UInt8 to text "n.n.n.n" -// 2, 4, 20, 22 - Latitude or longitude master -// 7 - special DateTime master, the time part +// 2, 4, 20, 22 - Latitude or longitude main +// 7 - special DateTime main, the time part // 27, 28 - explicitly encoded text // // Here are the GPS IFD tags that get mapped by type and count: @@ -163,7 +163,7 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // 296 SHORT 1 ResolutionUnit integer // 301 SHORT 3*256 TransferFunction integer seq // 305 ASCII Any Software text, xmp:CreatorTool -// 306 ASCII 20 DateTime date, master of 37520, xmp:DateTime +// 306 ASCII 20 DateTime date, main of 37520, xmp:DateTime // 315 ASCII Any Artist text, dc:creator[1] // 318 RATIONAL 2 WhitePoint rational seq // 319 RATIONAL 6 PrimaryChromaticities rational seq @@ -183,8 +183,8 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // 34855 SHORT Any ISOSpeedRatings integer seq // 34856 UNDEFINED Any OECF OECF/SFR table // 36864 UNDEFINED 4 ExifVersion text, Exif has 4 ASCII chars -// 36867 ASCII 20 DateTimeOriginal date, master of 37521 -// 36868 ASCII 20 DateTimeDigitized date, master of 37522 +// 36867 ASCII 20 DateTimeOriginal date, main of 37521 +// 36868 ASCII 20 DateTimeDigitized date, main of 37522 // 37121 UNDEFINED 4 ComponentsConfiguration integer seq, Exif has 4 UInt8 // 37122 RATIONAL 1 CompressedBitsPerPixel rational // 37377 SRATIONAL 1 ShutterSpeedValue rational @@ -237,12 +237,12 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // // 0 BYTE 4 GPSVersionID text, "n.n.n.n", Exif has 4 UInt8 // 1 ASCII 2 GPSLatitudeRef latitude, with 2 -// 2 RATIONAL 3 GPSLatitude latitude, master of 2 +// 2 RATIONAL 3 GPSLatitude latitude, main of 2 // 3 ASCII 2 GPSLongitudeRef longitude, with 4 -// 4 RATIONAL 3 GPSLongitude longitude, master of 3 +// 4 RATIONAL 3 GPSLongitude longitude, main of 3 // 5 BYTE 1 GPSAltitudeRef integer // 6 RATIONAL 1 GPSAltitude rational -// 7 RATIONAL 3 GPSTimeStamp date, master of 29 +// 7 RATIONAL 3 GPSTimeStamp date, main of 29 // 8 ASCII Any GPSSatellites text // 9 ASCII 2 GPSStatus text // 10 ASCII 2 GPSMeasureMode text @@ -255,9 +255,9 @@ extern void ExportPhotoData ( XMP_FileFormat destFormat, // 17 RATIONAL 1 GPSImgDirection rational // 18 ASCII Any GPSMapDatum text // 19 ASCII 2 GPSDestLatitudeRef latitude, with 20 -// 20 RATIONAL 3 GPSDestLatitude latitude, master of 19 +// 20 RATIONAL 3 GPSDestLatitude latitude, main of 19 // 21 ASCII 2 GPSDestLongitudeRef longitude, with 22 -// 22 RATIONAL 3 GPSDestLongitude logitude, master of 21 +// 22 RATIONAL 3 GPSDestLongitude logitude, main of 21 // 23 ASCII 2 GPSDestBearingRef text // 24 RATIONAL 1 GPSDestBearing rational // 25 ASCII 2 GPSDestDistanceRef text diff --git a/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp b/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp index 99c9fd1..a3e6d79 100644 --- a/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp +++ b/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp @@ -118,6 +118,9 @@ static const TIFF_MappingToXMP sExifIFDMappings[] = { { /* 40964 */ kTIFF_RelatedSoundFile, kTIFF_ASCIIType, kAnyCount, kExport_Always, kXMP_NS_EXIF, "RelatedSoundFile" }, // ! Exif spec says count of 13. { /* 36867 */ kTIFF_DateTimeOriginal, kTIFF_ASCIIType, 20, kExport_Always, "", "" }, // ! Has a special mapping. { /* 36868 */ kTIFF_DateTimeDigitized, kTIFF_ASCIIType, 20, kExport_Always, "", "" }, // ! Has a special mapping. + { /* 36880 */ kTIFF_OffsetTime, kTIFF_ASCIIType, 7, kExport_Always, "", "" }, // ! Has a special mapping. + { /* 36881 */ kTIFF_OffsetTimeOriginal, kTIFF_ASCIIType, 7, kExport_Always, "", "" }, // ! Has a special mapping. + { /* 36882 */ kTIFF_OffsetTimeDigitized, kTIFF_ASCIIType, 7, kExport_Always, "", "" }, // ! Has a special mapping. { /* 42016 */ kTIFF_ImageUniqueID, kTIFF_ASCIIType, 33, kExport_InjectOnly, kXMP_NS_EXIF, "ImageUniqueID" }, { /* 42032 */ kTIFF_CameraOwnerName, kTIFF_ASCIIType, kAnyCount, kExport_InjectOnly, kXMP_NS_ExifEX, "CameraOwnerName" }, { /* 42033 */ kTIFF_BodySerialNumber, kTIFF_ASCIIType, kAnyCount, kExport_InjectOnly, kXMP_NS_ExifEX, "BodySerialNumber" }, @@ -1252,6 +1255,14 @@ ImportTIFF_StandardMappings ( XMP_Uns8 ifd, const TIFF_Manager & tiff, SXMPMeta bool found = tiff.GetTag ( ifd, mapInfo.id, &tagInfo ); if ( ! found ) continue; + /* tag length need to be checked in case of TIFF_MemoryReader, as a possible case + the data length value might be changed (flippig because of endianess) by next overlapping IFD leading to crash. + To avoid that, rechecking the datalen just before its access. Fixing CTECHXMP-4170409*/ + if(tiff.IsCheckTagLength() && + tagInfo.dataLen > tiff.GetTiffLength() - ((XMP_Uns8*)tagInfo.dataPtr - tiff.GetTiffStream())) { + continue; // Bad Tag + } + XMP_Assert ( tagInfo.type != kTIFF_UndefinedType ); // These must have a special mapping. if ( tagInfo.type == kTIFF_UndefinedType ) continue; @@ -1281,7 +1292,7 @@ ImportTIFF_StandardMappings ( XMP_Uns8 ifd, const TIFF_Manager & tiff, SXMPMeta // ImportTIFF_Date // =============== // -// Convert an Exif 2.2 master date/time tag plus associated fractional seconds to an XMP date/time. +// Convert an Exif 2.2 main date/time tag plus associated fractional seconds to an XMP date/time. // The Exif date/time part is a 20 byte ASCII value formatted as "YYYY:MM:DD HH:MM:SS" with a // terminating nul. Any of the numeric portions can be blanks if unknown. The fractional seconds // are a nul terminated ASCII string with possible space padding. They are literally the fractional @@ -1291,11 +1302,14 @@ static void ImportTIFF_Date ( const TIFF_Manager & tiff, const TIFF_Manager::TagInfo & dateInfo, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ) { - XMP_Uns16 secID = 0; + XMP_Uns16 secID = 0, offsetID = 0; switch ( dateInfo.id ) { - case kTIFF_DateTime : secID = kTIFF_SubSecTime; break; - case kTIFF_DateTimeOriginal : secID = kTIFF_SubSecTimeOriginal; break; - case kTIFF_DateTimeDigitized : secID = kTIFF_SubSecTimeDigitized; break; + case kTIFF_DateTime : secID = kTIFF_SubSecTime; + offsetID = kTIFF_OffsetTime; break; + case kTIFF_DateTimeOriginal : secID = kTIFF_SubSecTimeOriginal; + offsetID = kTIFF_OffsetTimeOriginal; break; + case kTIFF_DateTimeDigitized : secID = kTIFF_SubSecTimeDigitized; + offsetID = kTIFF_OffsetTimeDigitized; break; } try { // Don't let errors with one stop the others. @@ -1336,7 +1350,31 @@ ImportTIFF_Date ( const TIFF_Manager & tiff, const TIFF_Manager::TagInfo & dateI for ( ; digits < 9; ++digits ) binValue.nanoSecond *= 10; if ( binValue.nanoSecond != 0 ) binValue.hasTime = true; } + // The offset time tags were added to EXIF spec 2.3.1., therefore we not + // supporting read/write in older versions + // We need EXIF spec version to figure out the same. + bool haveOldExif = true; // Default to old Exif if no version tag. + TIFF_Manager::TagInfo tagInfo; + bool foundExif = tiff.GetTag ( kTIFF_ExifIFD, kTIFF_ExifVersion, &tagInfo ); + if ( foundExif && (tagInfo.type == kTIFF_UndefinedType) && (tagInfo.count == 4) ) { + haveOldExif = (strncmp ( (char*)tagInfo.dataPtr, "0231", 4 ) < 0); + } + + if (!haveOldExif) + { + TIFF_Manager::TagInfo timezoneInfo; + found = tiff.GetTag ( kTIFF_ExifIFD, offsetID, &timezoneInfo ); + if ( found && (timezoneInfo.type == kTIFF_ASCIIType) && (timezoneInfo.count == 7) ) { + const char * timezoneStr = (const char *) timezoneInfo.dataPtr; + if ( (timezoneStr[0] == '+') || (timezoneStr[0] == '-') || (timezoneStr[3] == ':') ) { + binValue.tzSign = (timezoneStr[0] == '-') ? -1 : 1; + binValue.tzHour = GatherInt ( &timezoneStr[1], 2 ); + binValue.tzMinute = GatherInt ( &timezoneStr[4], 2 ); + binValue.hasTimeZone = true; + } + } + } xmp->SetProperty_Date ( xmpNS, xmpProp, binValue ); } catch ( ... ) { @@ -2209,13 +2247,13 @@ PhotoDataUtils::Import2WayExif ( const TIFF_Manager & exif, SXMPMeta * xmp, int xmp->SetProperty ( kXMP_NS_EXIF, "GPSVersionID", strOut ); } - // 2 GPSLatitude is a GPS coordinate master. + // 2 GPSLatitude is a GPS coordinate main. found = exif.GetTag ( kTIFF_GPSInfoIFD, kTIFF_GPSLatitude, &tagInfo ); if ( found ) { ImportTIFF_GPSCoordinate ( exif, tagInfo, xmp, kXMP_NS_EXIF, "GPSLatitude" ); } - // 4 GPSLongitude is a GPS coordinate master. + // 4 GPSLongitude is a GPS coordinate main. found = exif.GetTag ( kTIFF_GPSInfoIFD, kTIFF_GPSLongitude, &tagInfo ); if ( found ) { ImportTIFF_GPSCoordinate ( exif, tagInfo, xmp, kXMP_NS_EXIF, "GPSLongitude" ); @@ -2227,13 +2265,13 @@ PhotoDataUtils::Import2WayExif ( const TIFF_Manager & exif, SXMPMeta * xmp, int ImportTIFF_GPSTimeStamp ( exif, tagInfo, xmp, kXMP_NS_EXIF, "GPSTimeStamp" ); } - // 20 GPSDestLatitude is a GPS coordinate master. + // 20 GPSDestLatitude is a GPS coordinate main. found = exif.GetTag ( kTIFF_GPSInfoIFD, kTIFF_GPSDestLatitude, &tagInfo ); if ( found ) { ImportTIFF_GPSCoordinate ( exif, tagInfo, xmp, kXMP_NS_EXIF, "GPSDestLatitude" ); } - // 22 GPSDestLongitude is a GPS coordinate master. + // 22 GPSDestLongitude is a GPS coordinate main. found = exif.GetTag ( kTIFF_GPSInfoIFD, kTIFF_GPSDestLongitude, &tagInfo ); if ( found ) { ImportTIFF_GPSCoordinate ( exif, tagInfo, xmp, kXMP_NS_EXIF, "GPSDestLongitude" ); @@ -2690,7 +2728,7 @@ ExportTIFF_StandardMappings ( XMP_Uns8 ifd, TIFF_Manager * tiff, const SXMPMeta // ExportTIFF_Date // =============== // -// Convert an XMP date/time to an Exif 2.2 master date/time tag plus associated fractional seconds. +// Convert an XMP date/time to an Exif 2.2 main date/time tag plus associated fractional seconds. // The Exif date/time part is a 20 byte ASCII value formatted as "YYYY:MM:DD HH:MM:SS" with a // terminating nul. The fractional seconds are a nul terminated ASCII string with possible space // padding. They are literally the fractional part, the digits that would be to the right of the @@ -2701,10 +2739,18 @@ ExportTIFF_Date ( const SXMPMeta & xmp, const char * xmpNS, const char * xmpProp { XMP_Uns8 mainIFD = kTIFF_ExifIFD; XMP_Uns16 fracID=0; + XMP_Uns16 offsetID=0; switch ( mainID ) { - case kTIFF_DateTime : mainIFD = kTIFF_PrimaryIFD; fracID = kTIFF_SubSecTime; break; - case kTIFF_DateTimeOriginal : fracID = kTIFF_SubSecTimeOriginal; break; - case kTIFF_DateTimeDigitized : fracID = kTIFF_SubSecTimeDigitized; break; + case kTIFF_DateTime : mainIFD = kTIFF_PrimaryIFD; + fracID = kTIFF_SubSecTime; + offsetID = kTIFF_OffsetTime; + break; + case kTIFF_DateTimeOriginal : fracID = kTIFF_SubSecTimeOriginal; + offsetID = kTIFF_OffsetTimeOriginal; + break; + case kTIFF_DateTimeDigitized : fracID = kTIFF_SubSecTimeDigitized; + offsetID = kTIFF_OffsetTimeDigitized; + break; } try { // Don't let errors with one stop the others. @@ -2714,6 +2760,7 @@ ExportTIFF_Date ( const SXMPMeta & xmp, const char * xmpNS, const char * xmpProp if ( ! foundXMP ) { tiff->DeleteTag ( mainIFD, mainID ); tiff->DeleteTag ( kTIFF_ExifIFD, fracID ); // ! The subseconds are always in the Exif IFD. + tiff->DeleteTag ( kTIFF_ExifIFD, offsetID );// ! The offsetTime are always in the Exif IFD. return; } @@ -2758,23 +2805,53 @@ ExportTIFF_Date ( const SXMPMeta & xmp, const char * xmpNS, const char * xmpProp if ( xmpBin.nanoSecond == 0 ) { tiff->DeleteTag ( kTIFF_ExifIFD, fracID ); - - } else { - - snprintf ( buffer, sizeof(buffer), "%09d", xmpBin.nanoSecond ); // AUDIT: Use of sizeof(buffer) is safe. - for ( size_t i = strlen(buffer)-1; i > 0; --i ) { - if ( buffer[i] != '0' ) break; - buffer[i] = 0; // Strip trailing zero digits. + } + else + { + snprintf(buffer, sizeof(buffer), "%09d", xmpBin.nanoSecond); // AUDIT: Use of sizeof(buffer) is safe. + for (size_t i = strlen(buffer) - 1; i > 0; --i) + { + if (buffer[i] != '0') + break; + buffer[i] = 0; // Strip trailing zero digits. } + tiff->SetTag_ASCII(kTIFF_ExifIFD, fracID, buffer); // ! The subseconds are always in the Exif IFD. + } - tiff->SetTag_ASCII ( kTIFF_ExifIFD, fracID, buffer ); // ! The subseconds are always in the Exif IFD. + bool haveOldExif = true; // Default to old Exif if no version tag. + TIFF_Manager::TagInfo tagInfo; + bool foundExif = tiff->GetTag ( kTIFF_ExifIFD, kTIFF_ExifVersion, &tagInfo ); + if ( foundExif && (tagInfo.type == kTIFF_UndefinedType) && (tagInfo.count == 4) ) { + haveOldExif = (strncmp ( (char*)tagInfo.dataPtr, "0231", 4 ) < 0); + } + if (!haveOldExif) + { + // The offset time tags were added to EXIF spec 2.3.1., therefore we are not + // supporting read/write in older versions + // We need EXIF spec version to figure out the same. + + if ( xmpBin.hasTimeZone == 0 || (xmpBin.tzSign != -1 && xmpBin.tzSign != 1) ){ + + tiff->DeleteTag ( kTIFF_ExifIFD, offsetID ); + }else + { + char tzSign = '+'; + if (xmpBin.tzSign == -1) + tzSign = '-'; + + char offsetBuffer[7]; + snprintf(offsetBuffer, sizeof(offsetBuffer), "%c%02d:%02d", // AUDIT: Use of sizeof(offsetBuffer) is safe. + tzSign, xmpBin.tzHour, xmpBin.tzMinute); + + tiff->SetTag_ASCII(kTIFF_ExifIFD, offsetID, offsetBuffer); // ! The OffsetTime are always in the Exif IFD. + } } } catch ( ... ) { // Do nothing, let other exports proceed. // ? Notify client? - } + } } // ExportTIFF_Date diff --git a/XMPFiles/source/FormatSupport/SVG_Adapter.cpp b/XMPFiles/source/FormatSupport/SVG_Adapter.cpp index 34daa9e..c21d60c 100644 --- a/XMPFiles/source/FormatSupport/SVG_Adapter.cpp +++ b/XMPFiles/source/FormatSupport/SVG_Adapter.cpp @@ -3,14 +3,14 @@ // All Rights Reserved. // // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms -// of the Adobe license agreement accompanying it. If you have received this file from a source other +// of the Adobe license agreement accompanying it. If you have received this file from a source other // than Adobe, then your use, modification, or distribution of it requires the prior written permission // of Adobe. // -// This file includes implementation of SVG metadata, according to Scalable Vector Graphics (SVG) 1.1 Specification. +// This file includes implementation of SVG metadata, according to Scalable Vector Graphics (SVG) 1.1 Specification. // "https://www.w3.org/TR/2003/REC-SVG11-20030114/" -// Copyright © 1994-2002 World Wide Web Consortium, (Massachusetts Institute of Technology, -// Institut National de Recherche en Informatique et en Automatique, Keio University). +// Copyright © 1994-2002 World Wide Web Consortium, (Massachusetts Institute of Technology, +// Institut National de Recherche en Informatique et en Automatique, Keio University). // All Rights Reserved . http://www.w3.org/Consortium/Legal // // ================================================================================================= diff --git a/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp b/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp index c58d55b..3e34d4e 100644 --- a/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp +++ b/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp @@ -972,17 +972,17 @@ void TIFF_FileWriter::IntegrateFromPShop6 ( const void * buriedPtr, size_t burie } // TIFF_FileWriter::IntegrateFromPShop6 // ================================================================================================= -// TIFF_FileWriter::CopyTagToMasterIFD +// TIFF_FileWriter::CopyTagToMainIFD // =================================== // -// Create a new master IFD entry from a buried Photoshop 6 IFD entry. Don't try to get clever with +// Create a new main IFD entry from a buried Photoshop 6 IFD entry. Don't try to get clever with // large values, just create a new copy. This preserves a clean separation between the memory-based // and file-based TIFF processing. -void* TIFF_FileWriter::CopyTagToMasterIFD ( const TagInfo & ps6Tag, InternalIFDInfo * masterIFD ) +void* TIFF_FileWriter::CopyTagToMainIFD ( const TagInfo & ps6Tag, InternalIFDInfo * mainIFD ) { InternalTagMap::value_type mapValue ( ps6Tag.id, InternalTagInfo ( ps6Tag.id, ps6Tag.type, ps6Tag.count, this->fileParsed ) ); - InternalTagMap::iterator newPos = masterIFD->tagMap.insert ( masterIFD->tagMap.end(), mapValue ); + InternalTagMap::iterator newPos = mainIFD->tagMap.insert ( mainIFD->tagMap.end(), mapValue ); InternalTagInfo& newTag = newPos->second; newTag.dataLen = ps6Tag.dataLen; @@ -999,11 +999,11 @@ void* TIFF_FileWriter::CopyTagToMasterIFD ( const TagInfo & ps6Tag, InternalIFDI newTag.changed = true; // ! See comments with ProcessPShop6IFD. XMP_Assert ( (newTag.origDataLen == 0) && (newTag.origDataOffset == 0) ); - masterIFD->changed = true; + mainIFD->changed = true; return newPos->second.dataPtr; // ! Return the address within the map entry for small values. -} // TIFF_FileWriter::CopyTagToMasterIFD +} // TIFF_FileWriter::CopyTagToMainIFD // ================================================================================================= // FlipCFATable @@ -1017,10 +1017,10 @@ static bool FlipCFATable ( void* voidPtr, XMP_Uns32 tagLen, GetUns16_Proc GetUns XMP_Uns16* u16Ptr = (XMP_Uns16*)voidPtr; - Flip2 ( &u16Ptr[0] ); // Flip the counts to match the master TIFF. + Flip2 ( &u16Ptr[0] ); // Flip the counts to match the main TIFF. Flip2 ( &u16Ptr[1] ); - XMP_Uns16 columns = GetUns16 ( &u16Ptr[0] ); // Fetch using the master TIFF's routine. + XMP_Uns16 columns = GetUns16 ( &u16Ptr[0] ); // Fetch using the main TIFF's routine. XMP_Uns16 rows = GetUns16 ( &u16Ptr[1] ); if ( tagLen != (XMP_Uns32)(4 + columns*rows) ) return false; @@ -1062,10 +1062,10 @@ static bool FlipOECFSFRTable ( void* voidPtr, XMP_Uns32 tagLen, GetUns16_Proc Ge { XMP_Uns16* u16Ptr = (XMP_Uns16*)voidPtr; - Flip2 ( &u16Ptr[0] ); // Flip the data to match the master TIFF. + Flip2 ( &u16Ptr[0] ); // Flip the data to match the main TIFF. Flip2 ( &u16Ptr[1] ); - XMP_Uns16 columns = GetUns16 ( &u16Ptr[0] ); // Fetch using the master TIFF's routine. + XMP_Uns16 columns = GetUns16 ( &u16Ptr[0] ); // Fetch using the main TIFF's routine. XMP_Uns16 rows = GetUns16 ( &u16Ptr[1] ); XMP_Uns32 minLen = 4 + columns + (8 * columns * rows); // Minimum legit tag size. @@ -1112,25 +1112,25 @@ void TIFF_FileWriter::ProcessPShop6IFD ( const TIFF_MemoryReader& buriedExif, XM bool needsFlipping = (this->bigEndian != buriedExif.IsBigEndian()); - InternalIFDInfo* masterIFD = &this->containedIFDs[ifd]; + InternalIFDInfo* mainIFD = &this->containedIFDs[ifd]; TagInfoMap::const_iterator ps6Pos = ps6IFD.begin(); TagInfoMap::const_iterator ps6End = ps6IFD.end(); for ( ; ps6Pos != ps6End; ++ps6Pos ) { - // Copy buried tags to the master IFD if they don't already exist there. + // Copy buried tags to the main IFD if they don't already exist there. const TagInfo& ps6Tag = ps6Pos->second; - if ( this->FindTagInIFD ( ifd, ps6Tag.id ) != 0 ) continue; // Keep existing master tags. + if ( this->FindTagInIFD ( ifd, ps6Tag.id ) != 0 ) continue; // Keep existing main tags. if ( needsFlipping && (ps6Tag.id == 37500) ) continue; // Don't copy an unflipped MakerNote. if ( (ps6Tag.id == kTIFF_ExifIFDPointer) || // Skip the tags that are explicit offsets. (ps6Tag.id == kTIFF_GPSInfoIFDPointer) || (ps6Tag.id == kTIFF_JPEGInterchangeFormat) || (ps6Tag.id == kTIFF_InteroperabilityIFDPointer) ) continue; - void* voidPtr = this->CopyTagToMasterIFD ( ps6Tag, masterIFD ); + void* voidPtr = this->CopyTagToMainIFD ( ps6Tag, mainIFD ); if ( needsFlipping ) { switch ( ps6Tag.type ) { @@ -1510,8 +1510,9 @@ void TIFF_FileWriter::UpdateMemByAppend ( XMP_Uns8** newStream_out, XMP_Uns32* n if ( (appendAll | currTag.changed) && (currTag.dataLen > 4) ) { XMP_Uns32 valueOffset = this->GetUns32 ( &currTag.smallValue ); + bool inplaceUpdate = (currTag.dataLen <= currTag.origDataLen) && (! appendAll); - if ( (currTag.dataLen <= currTag.origDataLen) && (! appendAll) ) { + if ( inplaceUpdate ) { XMP_Assert ( valueOffset == currTag.origDataOffset ); } else { XMP_Assert ( valueOffset == appendedOffset ); @@ -1521,7 +1522,10 @@ void TIFF_FileWriter::UpdateMemByAppend ( XMP_Uns8** newStream_out, XMP_Uns32* n XMP_Assert ( valueOffset <= newLength ); // Provably true, valueOffset is in the old span, newLength is the new bigger span. if ( currTag.dataLen > (newLength - valueOffset) ) XMP_Throw ( "Buffer overrun", kXMPErr_InternalFailure ); memcpy ( (newStream + valueOffset), currTag.dataPtr, currTag.dataLen ); // AUDIT: Protected by the above check. - if ( (currTag.dataLen & 1) != 0 ) newStream[valueOffset+currTag.dataLen] = 0; + if ( !inplaceUpdate && ((currTag.dataLen & 1) != 0) ) { + newStream[valueOffset+currTag.dataLen] = 0; + + } } diff --git a/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp b/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp index 8b0ae29..b85a904 100644 --- a/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp +++ b/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp @@ -72,7 +72,7 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD ) } else if ( thisTag == prevTag ) { // Duplicate tag, keep the 2nd copy, move the tail of the array up, prevTag is unchanged. - memcpy ( &ifdEntries[i-1], &ifdEntries[i], 12*(tagCount-i) ); // AUDIT: Safe, moving tail forward, i >= 1. + memmove ( &ifdEntries[i-1], &ifdEntries[i], 12*(tagCount-i) ); // AUDIT: Safe, moving tail forward, i >= 1. --tagCount; --i; // ! Don't move forward in the array, we've moved the unseen part up. @@ -88,7 +88,7 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD ) // Out of order duplicate, move it to position j, move the tail of the array up. ifdEntries[j] = ifdEntries[i]; - memcpy ( &ifdEntries[i], &ifdEntries[i+1], 12*(tagCount-(i+1)) ); // AUDIT: Safe, moving tail forward, i >= 1. + memmove ( &ifdEntries[i], &ifdEntries[i+1], 12*(tagCount-(i+1)) ); // AUDIT: Safe, moving tail forward, i >= 1. --tagCount; --i; // ! Don't move forward in the array, we've moved the unseen part up. @@ -98,14 +98,14 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD ) #if ! (SUNOS_SPARC || XMP_IOS_ARM || XMP_ANDROID_ARM) TweakedIFDEntry temp = ifdEntries[i]; ++j; // ! So the insertion index becomes j. - memcpy ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // AUDIT: Safe, moving less than i entries to a location before i. + memmove ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // AUDIT: Safe, moving less than i entries to a location before i. ifdEntries[j] = temp; #else void * tempifdEntries = &ifdEntries[i]; TweakedIFDEntry temp; memcpy ( &temp, tempifdEntries, sizeof(TweakedIFDEntry) ); ++j; // ! So the insertion index becomes j. - memcpy ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // AUDIT: Safe, moving less than i entries to a location before i. + memmove ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // AUDIT: Safe, moving less than i entries to a location before i. tempifdEntries = &ifdEntries[j]; memcpy ( tempifdEntries, &temp, sizeof(TweakedIFDEntry) ); #endif diff --git a/XMPFiles/source/FormatSupport/TIFF_Support.hpp b/XMPFiles/source/FormatSupport/TIFF_Support.hpp index aad50b6..d2a0e2b 100644 --- a/XMPFiles/source/FormatSupport/TIFF_Support.hpp +++ b/XMPFiles/source/FormatSupport/TIFF_Support.hpp @@ -99,9 +99,9 @@ enum { // Constants for the type field of a tag, as defined by TIFF. static const size_t kTIFF_TypeSizes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4 }; -static const bool kTIFF_IsIntegerType[] = { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0 }; -static const bool kTIFF_IsRationalType[] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }; -static const bool kTIFF_IsFloatType[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 }; +static const bool kTIFF_IsIntegerType[] = { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0 ,0 }; +static const bool kTIFF_IsRationalType[] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 ,0 }; +static const bool kTIFF_IsFloatType[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 ,0 }; static const char * kTIFF_TypeNames[] = { "ShortOrLong", "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL", "SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL", @@ -193,6 +193,9 @@ enum { kTIFF_RelatedSoundFile = 40964, kTIFF_DateTimeOriginal = 36867, kTIFF_DateTimeDigitized = 36868, + kTIFF_OffsetTime = 36880, + kTIFF_OffsetTimeOriginal = 36881, + kTIFF_OffsetTimeDigitized = 36882, kTIFF_SubSecTime = 37520, kTIFF_SubSecTimeOriginal = 37521, kTIFF_SubSecTimeDigitized = 37522, @@ -366,6 +369,9 @@ static const XMP_Uns16 sKnownExifIFDTags[] = kTIFF_ExifVersion, // 36864 kTIFF_DateTimeOriginal, // 36867 kTIFF_DateTimeDigitized, // 36868 + kTIFF_OffsetTime, // 36880 + kTIFF_OffsetTimeOriginal, // 36881 + kTIFF_OffsetTimeDigitized, // 36882 kTIFF_ComponentsConfiguration, // 37121 kTIFF_CompressedBitsPerPixel, // 37122 kTIFF_ShutterSpeedValue, // 37377 @@ -518,6 +524,8 @@ public: bool IsBigEndian() const { return this->bigEndian; }; bool IsLittleEndian() const { return (! this->bigEndian); }; bool IsNativeEndian() const { return this->nativeEndian; }; + bool IsCheckTagLength () const { return this->checkTagLength; } + // --------------------------------------------------------------------------------------------- // The TIFF_Manager only keeps explicit knowledge of up to 4 IFDs: @@ -563,6 +571,9 @@ public: // new tag will have type short or long. virtual bool GetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32* data ) const = 0; + virtual XMP_Uns32 GetTiffLength() const = 0; + + virtual XMP_Uns8 *GetTiffStream() const = 0; void SetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32 data ); @@ -677,6 +688,7 @@ public: protected: bool bigEndian, nativeEndian; + bool checkTagLength { false }; XMP_Uns32 CheckTIFFHeader ( const XMP_Uns8* tiffPtr, XMP_Uns32 length ); // The pointer is to a buffer of the first 8 bytes. The length is the overall length, used @@ -738,6 +750,9 @@ public: bool GetTag_ASCII ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_StringPtr* dataPtr, XMP_StringLen* dataLen ) const; bool GetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, std::string* utf8Str ) const; + XMP_Uns32 GetTiffLength() const { return tiffLength; } + + XMP_Uns8 *GetTiffStream() const { return tiffStream; } void SetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, const std::string& utf8Str, XMP_Uns8 encoding ) { NotAppropriate(); }; @@ -753,7 +768,9 @@ public: XMP_Uns32 UpdateMemoryStream ( void** dataPtr, bool condenseStream = false ) { if ( dataPtr != 0 ) *dataPtr = tiffStream; return tiffLength; }; void UpdateFileStream ( XMP_IO* fileRef, XMP_ProgressTracker* progressTracker ) { NotAppropriate(); }; - TIFF_MemoryReader() : ownedStream(false), tiffStream(0), tiffLength(0) {}; + TIFF_MemoryReader() : ownedStream(false), tiffStream(0), tiffLength(0) { + checkTagLength = true; + }; virtual ~TIFF_MemoryReader() { if ( this->ownedStream ) free ( this->tiffStream ); }; @@ -847,6 +864,9 @@ public: bool GetTag_ASCII ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_StringPtr* dataPtr, XMP_StringLen* dataLen ) const; bool GetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, std::string* utf8Str ) const; + XMP_Uns32 GetTiffLength() const { return tiffLength; } + + XMP_Uns8 *GetTiffStream() const { return memStream; } void SetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, const std::string& utf8Str, XMP_Uns8 encoding ); @@ -966,7 +986,7 @@ private: void ProcessPShop6IFD ( const TIFF_MemoryReader& buriedExif, XMP_Uns8 ifd ); - void* CopyTagToMasterIFD ( const TagInfo& ps6Tag, InternalIFDInfo* masterIFD ); + void* CopyTagToMainIFD ( const TagInfo& ps6Tag, InternalIFDInfo* mainIFD ); void PreflightIFDLinkage(); diff --git a/XMPFiles/source/PluginHandler/FileHandlerInstance.cpp b/XMPFiles/source/PluginHandler/FileHandlerInstance.cpp index 2727c41..28218d0 100644 --- a/XMPFiles/source/PluginHandler/FileHandlerInstance.cpp +++ b/XMPFiles/source/PluginHandler/FileHandlerInstance.cpp @@ -25,8 +25,9 @@ XMPFileHandler( _parent ), mObject( object ), mHandler( handler ) FileHandlerInstance::~FileHandlerInstance() { WXMP_Error error; - mHandler->getModule()->getPluginAPIs()->mTerminateSessionProc( this->mObject, &error ); - PluginManager::removeHandlerInstance( this->mObject ); + + PluginManager::removeHandlerInstance(this->mObject); + mHandler->getModule()->getPluginAPIs()->mTerminateSessionProc(this->mObject, &error); CheckError( error ); } diff --git a/XMPFiles/source/WXMPFiles.cpp b/XMPFiles/source/WXMPFiles.cpp index 96b0af5..fae04c9 100644 --- a/XMPFiles/source/WXMPFiles.cpp +++ b/XMPFiles/source/WXMPFiles.cpp @@ -323,12 +323,15 @@ void WXMPFiles_GetXMP_1 ( XMPFilesRef xmpObjRef, StartPerfCheck ( kAPIPerf_GetXMP, "" ); bool hasXMP = false; - XMP_StringPtr packetStr; - XMP_StringLen packetLen; - - if ( xmpRef == 0 ) { + XMP_StringPtr packetStr = NULL; + XMP_StringLen packetLen = 0; + /*Adding check to handle case where a client might not send XMPMetaRef but still want xmp packet in return. eg. CTECHXMP-4170329*/ + if ( xmpRef == 0 && clientPacket != 0 ) { hasXMP = thiz->GetXMP ( 0, &packetStr, &packetLen, packetInfo ); - } else { + } else if ( xmpRef == 0 && clientPacket == 0 ) { + hasXMP = thiz->GetXMP( 0, 0, 0, packetInfo ); + } + else { SXMPMeta xmpObj ( xmpRef ); hasXMP = thiz->GetXMP ( &xmpObj, &packetStr, &packetLen, packetInfo ); } diff --git a/XMPFiles/source/XMPFiles.cpp b/XMPFiles/source/XMPFiles.cpp index a7ddb54..3721fb1 100644 --- a/XMPFiles/source/XMPFiles.cpp +++ b/XMPFiles/source/XMPFiles.cpp @@ -1482,7 +1482,11 @@ XMPFiles::GetXMP ( SXMPMeta * xmpObj /* = 0 */, */ if(! this->handler->processedXMP && !xmpObj && !(this->handler->xmpPacket.empty()) && packetInfo) - { + { + /*CTECHXMP-4170329: xmppacket and xmpPacketLen will only be populated if client has explicitly requested for xmp packet*/ + if ( xmpPacket != 0 ) *xmpPacket = this->handler->xmpPacket.c_str(); + if ( xmpPacketLen != 0 ) *xmpPacketLen = (XMP_StringLen)this->handler->xmpPacket.size(); + SetClientPacketInfo(packetInfo, this->handler->packetInfo, this->handler->xmpPacket, this->handler->needsUpdate ); return true; diff --git a/build/README.txt b/build/README.txt index 31bca61..98775be 100644 --- a/build/README.txt +++ b/build/README.txt @@ -1,23 +1,55 @@ -This README describes steps to generate project files on different platforms. These platform specific projects can then be used to build the XMPToolkit SDK. Before generating the projects the SDK developer needs to copy the dependencies to the proper locations. Refer to "Dependencies" section in the XMP Toolkit Programmer's Guide.
-
-WINDOWS 7 and above
-Options to generate Project files in Windows are of the form "Generate XMPSDKToolkit [Dynamic|static] [Win32|x64]". An option of "Dynamic" indicates that the generated project files will build a dll for the XMP SDK components. On the other hand the option of "Static" indicates that the generated project files will build a static lib for the XMP SDK components. Options for "Win32" or "x64" indicate that the generated project files will build the library for 32 bit or 64 bit applications respectively.
-1. Open the windows command prompt and change the current directory to <xmpsdk>/build.
2. Run the batch file GenerateXMPToolkitSDK_win.bat. There will be four options(2-5) to build projects for different configurations, one option(6) to generate projects for all configurations and one option(1) to clean all the projects.
3. After running the batch file (options 2-6),the vc14 projects(using cmake) will be generated at the location <xmpsdk>/build/vc14/<static|dynamic>/<windows|windows_x64>/<XMPToolkitSDK.sln|XMPToolkitSDK64.sln>.
4. Open the Visual Studio solution file and build XMP Toolkit SDK for debug/release configuration.
-MAC OS X 10.9 and above
-Options to generate Project files in Mac are of the form "Generate XMPSDKToolkit [Dynamic|static] [64|iOS]". An option of "Dynamic" indicates that the generated project files will build a framework for the XMP SDK components. On the other hand the option of "Static" indicates that the generated project files will build a static lib for the XMP SDK components. Option for "64" indicate that the generated project files will build for 64 bit applications. The option of "iOS" will generate the project files that will build XMP Core and XMP Files library for iOS simulators and iOS devices.
-1. Open the Terminal on Mac and change the current directory to <xmpsdk>/build.
2. Run the shell script GenerateXMPToolkitSDK_mac.sh. There will be three options(2-4) to build projects for different configurations, one option(5) to generate projects for all configurations and one option(1) to clean all the projects.
+This README describes steps to generate project files on different platforms. These platform specific projects can then be used to build the XMPToolkit SDK. Before generating the projects the SDK developer needs to copy the dependencies to the proper locations. Refer to "Dependencies" section in the XMP Toolkit Programmer's Guide.
+
+
+WINDOWS 7 and above
+
+Options to generate Project files in Windows are of the form "Generate XMPSDKToolkit [Dynamic|static] [Win32|x64]". An option of "Dynamic" indicates that the generated project files will build a dll for the XMP SDK components. On the other hand the option of "Static" indicates that the generated project files will build a static lib for the XMP SDK components. Options for "Win32" or "x64" indicate that the generated project files will build the library for 32 bit or 64 bit applications respectively.
+
+1. Open the windows command prompt and change the current directory to <xmpsdk>/build.
+2. Run the batch file GenerateXMPToolkitSDK_win.bat. There will be two options(2 & 3) to build projects for different configurations, one option(4) to generate projects for all configurations and one option(1) to clean all the projects.
+3. After running the batch file (options 2 & 3),the vc14 projects(using cmake) will be generated at the location <xmpsdk>/build/vc14/<static|dynamic>/windows_x64>/XMPToolkitSDK64.sln.
+4. Open the Visual Studio solution file and build XMP Toolkit SDK for debug/release configuration.
+
+MAC OS X 10.9 and above
+
+Options to generate Project files in Mac are of the form "Generate XMPSDKToolkit [Dynamic|static] [64|iOS]". An option of "Dynamic" indicates that the generated project files will build a framework for the XMP SDK components. On the other hand the option of "Static" indicates that the generated project files will build a static lib for the XMP SDK components. Option for "64" indicate that the generated project files will build for 64 bit applications. The option of "iOS" will generate the project files that will build XMP Core and XMP Files library for iOS simulators and iOS devices.
+
+1. Open the Terminal on Mac and change the current directory to <xmpsdk>/build.
+2. Run the shell script GenerateXMPToolkitSDK_mac.sh. There will be three options(2-4) to build projects for different configurations, one option(5) to generate projects for all configurations and one option(1) to clean all the projects.
3. After running the batch file (options 2-5),the xcode projects will be generated(using cmake) at the location <xmpsdk>/build/xcode/<static|dynamic>/<intel_64|ios>/<XMPToolkitSDK.xcodeproj|XMPToolkitSDK64.xcodeproj>.
-4. Open the xcodeproj file and build XMP Toolkit SDK for debug/release configuration.
-Note: When multiple Xcode versions are installed on a system, the developer has to use xcode-select command to specify the Xcode version that he/she wishes to use. This is done in two steps by fetching the current Xcode folder and changing it if required.
-1) Fetch the current Xcode folder
$ xcode-select -print-path
-2) Change the Xcode Folder if required. For example if the new XCode path is /Applications/Xcode.app
$ sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
Note: Presently a single scheme is created for each project. For building different configurations the Release or Debug configurations has to be selected using "Edit Scheme -> Run -> Release/Debug
-
LINUX
-Options to generate makefiles in Linux are given in the form of a Makefile with different targets. The targets available are
-StaticAll: Generates the Makefiles for static libraries and builds them. Includes both Debug and Release libs.
DynamicAll: Generates the Makefiles for shared libraries and builds them. Includes both Debug and Release libs.
DebugAll: Generates the Makefiles for Debug libraries and builds them. Includes both static and dynamic libs.
ReleaseAll: Generates the Makefiles for Release libraries and builds them. Includes both static and dynamic libs.
-1. Change the current directory to <xmpsdk>/build.
2. Make sure the gcc location is added to $PATH and its libraries location to $LD_LIBRARY_PATH. There is a need to add libuuid.so library path to the $LD_LIBRARY_PATH as well.
-3. This <xmpsdk>/build folder contains a Makefile which has different targets to build and the default is to build all of them. The Makefile generates the makefiles(using cmake) to build the project and then calls these makefiles to build the target.
-
-Note: Generating gcc Makefiles to build the project requires the path to the gcc set in the CMake toolchain file for Linux i.e. <xmpsdk>/build/shared/ToolchainGCC.cmake. In this file modifications must be done by the developer to set the CMAKE_FIND_ROOT_PATH so that CMake picks the desired gcc compiler. He/She may also want to change the parameter XMP_ENABLE_SECURE_SETTINGS as per the configured gcc.
- a) If the gcc is configured with --enable-libssp (can be checked by executing gcc -v), he/she has to set the variable XMP_GCC_LIBPATH inside of file <xmpsdk>/build/ProductConfig.cmake to the path containing the static lib( libssp.a). In this case he/she can set the variable the XMP_ENABLE_SECURE_SETTINGS on.
-b) If the gcc is configured with --disable-libssp, he/she has to set the variable XMP_ENABLE_SECURE_SETTINGS off.
-=================================================================================================================================================
Note: The projects for different platforms are generated using CMake. CMake generates projects with absolute paths so they cannot be copied from one place to other. If the project is to be moved, then the whole tree has to be copied to the new location and CMake should be invoked again.
+4. Open the xcodeproj file and build XMP Toolkit SDK for debug/release configuration.
+
+Note: When multiple Xcode versions are installed on a system, the developer has to use xcode-select command to specify the Xcode version that he/she wishes to use. This is done in two steps by fetching the current Xcode folder and changing it if required.
+
+1) Fetch the current Xcode folder
+ $ xcode-select -print-path
+
+2) Change the Xcode Folder if required. For example if the new XCode path is /Applications/Xcode.app
+ $ sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
+
+Note: Presently a single scheme is created for each project. For building different configurations the Release or Debug configurations has to be selected using "Edit Scheme -> Run -> Release/Debug
+
+LINUX
+
+Options to generate makefiles in Linux are given in the form of a Makefile with different targets. The targets available are
+
+StaticAll: Generates the Makefiles for static libraries and builds them. Includes both Debug and Release libs.
+DynamicAll: Generates the Makefiles for shared libraries and builds them. Includes both Debug and Release libs.
+DebugAll: Generates the Makefiles for Debug libraries and builds them. Includes both static and dynamic libs.
+ReleaseAll: Generates the Makefiles for Release libraries and builds them. Includes both static and dynamic libs.
+
+1. Change the current directory to <xmpsdk>/build.
+2. Make sure the gcc location is added to $PATH and its libraries location to $LD_LIBRARY_PATH. There is a need to add libuuid.so library path to the $LD_LIBRARY_PATH as well.
+3. This <xmpsdk>/build folder contains a Makefile which has different targets to build and the default is to build all of them. The Makefile generates the makefiles(using cmake) to build the project and then calls these makefiles to build the target.
+
+
+
+Note: Generating gcc Makefiles to build the project requires the path to the gcc set in the CMake toolchain file for Linux i.e. <xmpsdk>/build/shared/ToolchainGCC.cmake. In this file modifications must be done by the developer to set the CMAKE_FIND_ROOT_PATH so that CMake picks the desired gcc compiler. He/She may also want to change the parameter XMP_ENABLE_SECURE_SETTINGS as per the configured gcc.
+
+ a) If the gcc is configured with --enable-libssp (can be checked by executing gcc -v), he/she has to set the variable XMP_GCC_LIBPATH inside of file <xmpsdk>/build/ProductConfig.cmake to the path containing the static lib( libssp.a). In this case he/she can set the variable the XMP_ENABLE_SECURE_SETTINGS on.
+
+b) If the gcc is configured with --disable-libssp, he/she has to set the variable XMP_ENABLE_SECURE_SETTINGS off.
+
+=================================================================================================================================================
+
+Note: The projects for different platforms are generated using CMake. CMake generates projects with absolute paths so they cannot be copied from one place to other. If the project is to be moved, then the whole tree has to be copied to the new location and CMake should be invoked again.
diff --git a/build/shared/SharedConfig_Common.cmake b/build/shared/SharedConfig_Common.cmake index 67ca67a..6a34588 100644 --- a/build/shared/SharedConfig_Common.cmake +++ b/build/shared/SharedConfig_Common.cmake @@ -75,8 +75,8 @@ endfunction(SetupInternalBuildDirectory) function(SetupCompilerFlags) if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(OUTPUT_VARIABLE "") - # Execute GCC with the -dumpversion option, to give us a version string - execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-dumpversion" OUTPUT_VARIABLE GCC_VERSION_STRING) + # Execute GCC with the --version option, to give us a version string + execute_process(COMMAND ${CMAKE_CXX_COMPILER} "--version" OUTPUT_VARIABLE GCC_VERSION_STRING) # Match only the major and minor versions of the version string string(REGEX MATCH "[0-9]+.[0-9]+.[0-9]" GCC_MAJOR_MINOR_VERSION_STRING "${GCC_VERSION_STRING}") diff --git a/public/include/TXMPFiles.hpp b/public/include/TXMPFiles.hpp index 7d30917..8a3cbb9 100644 --- a/public/include/TXMPFiles.hpp +++ b/public/include/TXMPFiles.hpp @@ -541,7 +541,8 @@ public: /// /// If the file is opened for update (passing \c #kXMPFiles_OpenForUpdate), the disk file remains /// open until \c CloseFile() is called. The disk file is only updated once, when \c CloseFile() - /// is called, regardless of how many calls are made to \c PutXMP(). + /// is called, regardless of how many calls are made to \c PutXMP(). When in-place update is not possible + /// we might write into a temporary file and then swap for corruption/crash safety. /* Documenatation update for CTECHXMP-4170278*/ /// /// @param closeFlags Option flags for optional closing actions. This bit-flag constant is /// defined: diff --git a/tools/cmake/ReadMe.txt b/tools/cmake/ReadMe.txt index 7606474..7c0b864 100644 --- a/tools/cmake/ReadMe.txt +++ b/tools/cmake/ReadMe.txt @@ -7,7 +7,7 @@ To use CMake: Download the following recommended CMake distribution zipped package from the following links corresponding to the current platform (Windows, Mac, or Linux)
Windows ---- https://cmake.org/files/v3.15/cmake-3.15.5-win32-x86.zip
Mac OSX ---- https://cmake.org/files/v3.15/cmake-3.15.5-Darwin-x86_64.tar.gz
-Linux ---- https://cmake.org/files/v3.15/cmake-3.15.5-Linux-i386.tar.gz
+Linux ---- https://cmake.org/files/v3.15/cmake-3.15.5-Linux-x86_64.tar.gz
2. For Windows and Linux copy the folders /bin and /share into <xmpsdk>/tools/cmake/
For Mac:
|