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

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

@ -84,27 +84,36 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
private IccTagDataEntry[] ReadTagData(IccDataReader 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>();
for (int i = 0; i < tagTable.Length; i++)
foreach (IccTagTableEntry tag in tagTable)
{
IccTagDataEntry entry;
uint offset = tagTable[i].Offset;
if (store.ContainsKey(offset))
if (store.ContainsKey(tag.Offset))
{
entry = store[offset];
entry = store[tag.Offset];
}
else
{
entry = reader.ReadTagDataEntry(tagTable[i]);
store.Add(offset, entry);
try
{
entry = reader.ReadTagDataEntry(tag);
}
catch
{
// Ignore tags that could not be read
continue;
}
store.Add(tag.Offset, entry);
}
entry.TagSignature = tagTable[i].Signature;
entries[i] = entry;
entry.TagSignature = tag.Signature;
entries.Add(entry);
}
return entries;
return entries.ToArray();
}
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
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++)
{
uint tagSignature = reader.ReadUInt32();
uint tagOffset = 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