summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarpitapanda05 <79362772+arpitapanda05@users.noreply.github.com>2021-07-15 22:39:17 +0530
committerGitHub <noreply@github.com>2021-07-15 22:39:17 +0530
commit9c78968498f3321bd50c817bae585bb0936e5e08 (patch)
tree8321cb248be0159534e81a94297a04007b390c31
parent7e01e4691e7a4fe474b7220d1be338d44c888bbd (diff)
Security Fixes and Exif Time Zone Metadata Support
Co-authored-by: prigupta <prigupta@adobe.com>
-rw-r--r--XMPCore/source/XMPUtils-FileInfo.cpp9
-rw-r--r--XMPFiles/source/FileHandlers/FLV_Handler.cpp2
-rw-r--r--XMPFiles/source/FileHandlers/P2_Handler.cpp38
-rw-r--r--XMPFiles/source/FileHandlers/PSD_Handler.cpp14
-rw-r--r--XMPFiles/source/FileHandlers/SWF_Handler.cpp10
-rw-r--r--XMPFiles/source/FileHandlers/TIFF_Handler.cpp2
-rw-r--r--XMPFiles/source/FileHandlers/UCF_Handler.cpp7
-rw-r--r--XMPFiles/source/FileHandlers/UCF_Handler.hpp1
-rw-r--r--XMPFiles/source/FormatSupport/ASF_Support.cpp11
-rw-r--r--XMPFiles/source/FormatSupport/ID3_Support.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/P2_Support.cpp9
-rw-r--r--XMPFiles/source/FormatSupport/PNG_Support.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/PostScript_Support.cpp6
-rw-r--r--XMPFiles/source/FormatSupport/RIFF.cpp4
-rw-r--r--XMPFiles/source/FormatSupport/ReconcileLegacy.hpp24
-rw-r--r--XMPFiles/source/FormatSupport/ReconcileTIFF.cpp121
-rw-r--r--XMPFiles/source/FormatSupport/SVG_Adapter.cpp8
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp36
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp8
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_Support.hpp30
-rw-r--r--XMPFiles/source/PluginHandler/FileHandlerInstance.cpp5
-rw-r--r--XMPFiles/source/WXMPFiles.cpp13
-rw-r--r--XMPFiles/source/XMPFiles.cpp6
-rw-r--r--public/include/TXMPFiles.hpp3
24 files changed, 264 insertions, 107 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/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: