Browse Source

add a few guards around reading ICC profile data

pull/588/head
Johannes Bildstein 8 years ago
parent
commit
800ee0985f
  1. 10
      src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs
  2. 47
      src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs

10
src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Text; using System.Text;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
@ -11,7 +10,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary> /// </summary>
internal sealed partial class IccDataReader internal sealed partial class IccDataReader
{ {
private static readonly bool IsLittleEndian = BitConverter.IsLittleEndian;
private static readonly Encoding AsciiEncoding = Encoding.GetEncoding("ASCII"); private static readonly Encoding AsciiEncoding = Encoding.GetEncoding("ASCII");
/// <summary> /// <summary>
@ -34,6 +32,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
this.data = data; this.data = data;
} }
/// <summary>
/// Gets the length in bytes of the raw data
/// </summary>
public int DataLength
{
get { return this.data.Length; }
}
/// <summary> /// <summary>
/// Sets the reading position to the given value /// Sets the reading position to the given value
/// </summary> /// </summary>

47
src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs

@ -84,27 +84,36 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
private IccTagDataEntry[] ReadTagData(IccDataReader reader) private IccTagDataEntry[] ReadTagData(IccDataReader reader)
{ {
IccTagTableEntry[] tagTable = this.ReadTagTable(reader); IccTagTableEntry[] tagTable = this.ReadTagTable(reader);
var entries = new IccTagDataEntry[tagTable.Length]; var entries = new List<IccTagDataEntry>(tagTable.Length);
var store = new Dictionary<uint, IccTagDataEntry>(); var store = new Dictionary<uint, IccTagDataEntry>();
for (int i = 0; i < tagTable.Length; i++)
foreach (IccTagTableEntry tag in tagTable)
{ {
IccTagDataEntry entry; IccTagDataEntry entry;
uint offset = tagTable[i].Offset; if (store.ContainsKey(tag.Offset))
if (store.ContainsKey(offset))
{ {
entry = store[offset]; entry = store[tag.Offset];
} }
else else
{ {
entry = reader.ReadTagDataEntry(tagTable[i]); try
store.Add(offset, entry); {
entry = reader.ReadTagDataEntry(tag);
}
catch
{
// Ignore tags that could not be read
continue;
}
store.Add(tag.Offset, entry);
} }
entry.TagSignature = tagTable[i].Signature; entry.TagSignature = tag.Signature;
entries[i] = entry; entries.Add(entry);
} }
return entries; return entries.ToArray();
} }
private IccTagTableEntry[] ReadTagTable(IccDataReader reader) private IccTagTableEntry[] ReadTagTable(IccDataReader reader)
@ -112,17 +121,29 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
reader.SetIndex(128); // An ICC header is 128 bytes long reader.SetIndex(128); // An ICC header is 128 bytes long
uint tagCount = reader.ReadUInt32(); uint tagCount = reader.ReadUInt32();
var table = new IccTagTableEntry[tagCount];
// Prevent creating huge arrays because of corrupt profiles.
// A normal profile usually has 5-15 entries
if (tagCount > 100)
{
return new IccTagTableEntry[0];
}
var table = new List<IccTagTableEntry>((int)tagCount);
for (int i = 0; i < tagCount; i++) for (int i = 0; i < tagCount; i++)
{ {
uint tagSignature = reader.ReadUInt32(); uint tagSignature = reader.ReadUInt32();
uint tagOffset = reader.ReadUInt32(); uint tagOffset = reader.ReadUInt32();
uint tagSize = reader.ReadUInt32(); uint tagSize = reader.ReadUInt32();
table[i] = new IccTagTableEntry((IccProfileTag)tagSignature, tagOffset, tagSize);
// Exclude entries that have nonsense values and could cause exceptions further on
if (tagOffset < reader.DataLength && tagSize < reader.DataLength - 128)
{
table.Add(new IccTagTableEntry((IccProfileTag)tagSignature, tagOffset, tagSize));
}
} }
return table; return table.ToArray();
} }
} }
} }

Loading…
Cancel
Save