Skip to content

Commit 800ee09

Browse files
author
Johannes Bildstein
committed
add a few guards around reading ICC profile data
1 parent 72c5548 commit 800ee09

File tree

2 files changed

+42
-15
lines changed

2 files changed

+42
-15
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Six Labors and contributors.
22
// Licensed under the Apache License, Version 2.0.
33

4-
using System;
54
using System.Text;
65

76
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
@@ -11,7 +10,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
1110
/// </summary>
1211
internal sealed partial class IccDataReader
1312
{
14-
private static readonly bool IsLittleEndian = BitConverter.IsLittleEndian;
1513
private static readonly Encoding AsciiEncoding = Encoding.GetEncoding("ASCII");
1614

1715
/// <summary>
@@ -34,6 +32,14 @@ public IccDataReader(byte[] data)
3432
this.data = data;
3533
}
3634

35+
/// <summary>
36+
/// Gets the length in bytes of the raw data
37+
/// </summary>
38+
public int DataLength
39+
{
40+
get { return this.data.Length; }
41+
}
42+
3743
/// <summary>
3844
/// Sets the reading position to the given value
3945
/// </summary>

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

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,45 +84,66 @@ private IccProfileHeader ReadHeader(IccDataReader reader)
8484
private IccTagDataEntry[] ReadTagData(IccDataReader reader)
8585
{
8686
IccTagTableEntry[] tagTable = this.ReadTagTable(reader);
87-
var entries = new IccTagDataEntry[tagTable.Length];
87+
var entries = new List<IccTagDataEntry>(tagTable.Length);
8888
var store = new Dictionary<uint, IccTagDataEntry>();
89-
for (int i = 0; i < tagTable.Length; i++)
89+
90+
foreach (IccTagTableEntry tag in tagTable)
9091
{
9192
IccTagDataEntry entry;
92-
uint offset = tagTable[i].Offset;
93-
if (store.ContainsKey(offset))
93+
if (store.ContainsKey(tag.Offset))
9494
{
95-
entry = store[offset];
95+
entry = store[tag.Offset];
9696
}
9797
else
9898
{
99-
entry = reader.ReadTagDataEntry(tagTable[i]);
100-
store.Add(offset, entry);
99+
try
100+
{
101+
entry = reader.ReadTagDataEntry(tag);
102+
}
103+
catch
104+
{
105+
// Ignore tags that could not be read
106+
continue;
107+
}
108+
109+
store.Add(tag.Offset, entry);
101110
}
102111

103-
entry.TagSignature = tagTable[i].Signature;
104-
entries[i] = entry;
112+
entry.TagSignature = tag.Signature;
113+
entries.Add(entry);
105114
}
106115

107-
return entries;
116+
return entries.ToArray();
108117
}
109118

110119
private IccTagTableEntry[] ReadTagTable(IccDataReader reader)
111120
{
112121
reader.SetIndex(128); // An ICC header is 128 bytes long
113122

114123
uint tagCount = reader.ReadUInt32();
115-
var table = new IccTagTableEntry[tagCount];
116124

125+
// Prevent creating huge arrays because of corrupt profiles.
126+
// A normal profile usually has 5-15 entries
127+
if (tagCount > 100)
128+
{
129+
return new IccTagTableEntry[0];
130+
}
131+
132+
var table = new List<IccTagTableEntry>((int)tagCount);
117133
for (int i = 0; i < tagCount; i++)
118134
{
119135
uint tagSignature = reader.ReadUInt32();
120136
uint tagOffset = reader.ReadUInt32();
121137
uint tagSize = reader.ReadUInt32();
122-
table[i] = new IccTagTableEntry((IccProfileTag)tagSignature, tagOffset, tagSize);
138+
139+
// Exclude entries that have nonsense values and could cause exceptions further on
140+
if (tagOffset < reader.DataLength && tagSize < reader.DataLength - 128)
141+
{
142+
table.Add(new IccTagTableEntry((IccProfileTag)tagSignature, tagOffset, tagSize));
143+
}
123144
}
124145

125-
return table;
146+
return table.ToArray();
126147
}
127148
}
128149
}

0 commit comments

Comments
 (0)