Browse Source

Ignore invalid iptc tag values #1942

pull/1944/head
Brian Popow 4 years ago
parent
commit
38b5da4e19
  1. 41
      src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
  2. 103
      src/ImageSharp/Metadata/Profiles/IPTC/IptcTagExtensions.cs
  3. 2
      src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs

41
src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs

@ -16,6 +16,10 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
{
private Collection<IptcValue> values;
private const byte IptcTagMarkerByte = 0x1c;
private const uint MaxStandardDataTagSize = 0x7FFF;
/// <summary>
/// Initializes a new instance of the <see cref="IptcProfile"/> class.
/// </summary>
@ -78,7 +82,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
}
/// <inheritdoc/>
public IptcProfile DeepClone() => new IptcProfile(this);
public IptcProfile DeepClone() => new(this);
/// <summary>
/// Returns all values with the specified tag.
@ -207,7 +211,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
throw new ArgumentException("iptc tag is not a time or date type");
}
var formattedDate = tag.IsDate()
string formattedDate = tag.IsDate()
? dateTimeOffset.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture)
: dateTimeOffset.ToString("HHmmsszzzz", System.Globalization.CultureInfo.InvariantCulture)
.Replace(":", string.Empty);
@ -231,7 +235,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
/// </summary>
public void UpdateData()
{
var length = 0;
int length = 0;
foreach (IptcValue value in this.Values)
{
length += value.Length + 5;
@ -242,7 +246,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
int i = 0;
foreach (IptcValue value in this.Values)
{
this.Data[i++] = 28;
this.Data[i++] = IptcTagMarkerByte;
this.Data[i++] = 2;
this.Data[i++] = (byte)value.Tag;
this.Data[i++] = (byte)(value.Length >> 8);
@ -264,34 +268,29 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
this.values = new Collection<IptcValue>();
if (this.Data == null || this.Data[0] != 0x1c)
if (this.Data == null || this.Data[0] != IptcTagMarkerByte)
{
return;
}
int i = 0;
while (i + 4 < this.Data.Length)
int offset = 0;
while (offset + 4 < this.Data.Length)
{
if (this.Data[i++] != 28)
{
continue;
}
i++;
var tag = (IptcTag)this.Data[i++];
bool isValidTagMarker = this.Data[offset++] == IptcTagMarkerByte;
byte recordType = this.Data[offset++];
var tag = (IptcTag)this.Data[offset++];
int count = BinaryPrimitives.ReadInt16BigEndian(this.Data.AsSpan(i, 2));
i += 2;
uint byteCount = BinaryPrimitives.ReadUInt16BigEndian(this.Data.AsSpan(offset, 2));
offset += 2;
var iptcData = new byte[count];
if ((count > 0) && (i + count <= this.Data.Length))
if (isValidTagMarker && byteCount > 0 && (offset + byteCount <= this.Data.Length))
{
Buffer.BlockCopy(this.Data, i, iptcData, 0, count);
var iptcData = new byte[byteCount];
Buffer.BlockCopy(this.Data, offset, iptcData, 0, (int)byteCount);
this.values.Add(new IptcValue(tag, iptcData, false));
}
i += count;
offset += (int)byteCount;
}
}
}

103
src/ImageSharp/Metadata/Profiles/IPTC/IptcTagExtensions.cs

@ -13,60 +13,57 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
/// </summary>
/// <param name="tag">The tag to check the max length for.</param>
/// <returns>The maximum length.</returns>
public static int MaxLength(this IptcTag tag)
public static int MaxLength(this IptcTag tag) => tag switch
{
return tag switch
{
IptcTag.RecordVersion => 2,
IptcTag.ObjectType => 67,
IptcTag.ObjectAttribute => 68,
IptcTag.Name => 64,
IptcTag.EditStatus => 64,
IptcTag.EditorialUpdate => 2,
IptcTag.Urgency => 1,
IptcTag.SubjectReference => 236,
IptcTag.Category => 3,
IptcTag.SupplementalCategories => 32,
IptcTag.FixtureIdentifier => 32,
IptcTag.Keywords => 64,
IptcTag.LocationCode => 3,
IptcTag.LocationName => 64,
IptcTag.ReleaseDate => 8,
IptcTag.ReleaseTime => 11,
IptcTag.ExpirationDate => 8,
IptcTag.ExpirationTime => 11,
IptcTag.SpecialInstructions => 256,
IptcTag.ActionAdvised => 2,
IptcTag.ReferenceService => 10,
IptcTag.ReferenceDate => 8,
IptcTag.ReferenceNumber => 8,
IptcTag.CreatedDate => 8,
IptcTag.CreatedTime => 11,
IptcTag.DigitalCreationDate => 8,
IptcTag.DigitalCreationTime => 11,
IptcTag.OriginatingProgram => 32,
IptcTag.ProgramVersion => 10,
IptcTag.ObjectCycle => 1,
IptcTag.Byline => 32,
IptcTag.BylineTitle => 32,
IptcTag.City => 32,
IptcTag.SubLocation => 32,
IptcTag.ProvinceState => 32,
IptcTag.CountryCode => 3,
IptcTag.Country => 64,
IptcTag.OriginalTransmissionReference => 32,
IptcTag.Headline => 256,
IptcTag.Credit => 32,
IptcTag.Source => 32,
IptcTag.CopyrightNotice => 128,
IptcTag.Contact => 128,
IptcTag.Caption => 2000,
IptcTag.CaptionWriter => 32,
IptcTag.ImageType => 2,
IptcTag.ImageOrientation => 1,
_ => 256
};
}
IptcTag.RecordVersion => 2,
IptcTag.ObjectType => 67,
IptcTag.ObjectAttribute => 68,
IptcTag.Name => 64,
IptcTag.EditStatus => 64,
IptcTag.EditorialUpdate => 2,
IptcTag.Urgency => 1,
IptcTag.SubjectReference => 236,
IptcTag.Category => 3,
IptcTag.SupplementalCategories => 32,
IptcTag.FixtureIdentifier => 32,
IptcTag.Keywords => 64,
IptcTag.LocationCode => 3,
IptcTag.LocationName => 64,
IptcTag.ReleaseDate => 8,
IptcTag.ReleaseTime => 11,
IptcTag.ExpirationDate => 8,
IptcTag.ExpirationTime => 11,
IptcTag.SpecialInstructions => 256,
IptcTag.ActionAdvised => 2,
IptcTag.ReferenceService => 10,
IptcTag.ReferenceDate => 8,
IptcTag.ReferenceNumber => 8,
IptcTag.CreatedDate => 8,
IptcTag.CreatedTime => 11,
IptcTag.DigitalCreationDate => 8,
IptcTag.DigitalCreationTime => 11,
IptcTag.OriginatingProgram => 32,
IptcTag.ProgramVersion => 10,
IptcTag.ObjectCycle => 1,
IptcTag.Byline => 32,
IptcTag.BylineTitle => 32,
IptcTag.City => 32,
IptcTag.SubLocation => 32,
IptcTag.ProvinceState => 32,
IptcTag.CountryCode => 3,
IptcTag.Country => 64,
IptcTag.OriginalTransmissionReference => 32,
IptcTag.Headline => 256,
IptcTag.Credit => 32,
IptcTag.Source => 32,
IptcTag.CopyrightNotice => 128,
IptcTag.Contact => 128,
IptcTag.Caption => 2000,
IptcTag.CaptionWriter => 32,
IptcTag.ImageType => 2,
IptcTag.ImageOrientation => 1,
_ => 256
};
/// <summary>
/// Determines if the given tag can be repeated according to the specification.

2
src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs

@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
byte[] valueBytes;
if (this.Strict && value.Length > maxLength)
{
var cappedValue = value.Substring(0, maxLength);
string cappedValue = value.Substring(0, maxLength);
valueBytes = this.encoding.GetBytes(cappedValue);
// It is still possible that the bytes of the string exceed the limit.

Loading…
Cancel
Save