Fix buggy font (#283)

* Adds checksum on font file reading

* fix name table parsing on broken table

* only warn if checksum invalid, avoid exception with bounds check #258

also returns a null object when the object generation number exceeds
ushort.maxvalue since this is the maximum allowed value and this
broke tests attempting to parse all objects in the file from #258

* remove potentially problematic document

it might be sensitive data

* use ttf from file to test without including full file

Co-authored-by: romain v <rvergnory@lucca.fr>
This commit is contained in:
Eliot Jones 2021-02-07 12:23:11 -04:00 committed by GitHub
parent 9d99ac4e9b
commit 6f49b2e29e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 61 additions and 7 deletions

View File

@ -22,10 +22,19 @@
}
var strings = new TrueTypeNameRecord[count];
var offset = header.Offset + stringOffset;
for (var i = 0; i < count; i++)
{
var nameRecord = names[i];
strings[i] = GetTrueTypeNameRecord(names[i], data, offset);
}
return new NameTable(header, GetName(4, strings), GetName(1, strings), GetName(2, strings), strings);
}
private static TrueTypeNameRecord GetTrueTypeNameRecord(NameRecordBuilder nameRecord, TrueTypeDataBytes data, uint offset)
{
try
{
var encoding = OtherEncodings.Iso88591;
switch (nameRecord.PlatformId)
@ -62,16 +71,23 @@
}
}
var position = header.Offset + stringOffset + nameRecord.Offset;
var position = offset + nameRecord.Offset;
if (position >= data.Length)
{
return null;
}
data.Seek(position);
var str = data.ReadString(nameRecord.Length, encoding);
strings[i] = nameRecord.ToNameRecord(str);
return nameRecord.ToNameRecord(str);
}
catch
{
return null;
}
return new NameTable(header, GetName(4, strings), GetName(1, strings), GetName(2, strings), strings);
}
private static string GetName(int nameId, TrueTypeNameRecord[] names)
@ -84,7 +100,7 @@
{
var name = names[i];
if (name.NameId != nameId)
if (name is null || name.NameId != nameId)
{
continue;
}

View File

@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Fonts.TrueType.Parser
{
using System;
using System.Diagnostics;
using Tables;
internal static class TableParser
@ -13,6 +14,20 @@
public static T Parse<T>(TrueTypeHeaderTable table, TrueTypeDataBytes data, TableRegister.Builder register) where T : ITrueTypeTable
{
//checksum https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html
uint sum = 0;
var nLongs = (table.Length + 3) / 4;
data.Seek(table.Offset);
while (nLongs-- > 0)
{
sum += (uint)data.ReadSignedInt();
}
if (sum != table.CheckSum)
{
Trace.TraceWarning("Table with invalid checksum found in TrueType font file.");
}
if (typeof(T) == typeof(CMapTable))
{
return (T) (object) CMapTableParser.Parse(table, data, register);

View File

@ -61,7 +61,7 @@
string any = null;
foreach (var nameRecord in NameRecords)
{
if (nameRecord.NameId != 6)
if (nameRecord is null || nameRecord.NameId != 6)
{
continue;
}

View File

@ -210,6 +210,20 @@ namespace UglyToad.PdfPig.Tests.Fonts.TrueType.Parser
Assert.Equal(points, glyph.Points.Length);
}
}
[Fact]
public void ParseIssue258CorruptNameTable()
{
var bytes = TrueTypeTestHelper.GetFileBytes("issue-258-corrupt-name-table");
var input = new TrueTypeDataBytes(new ByteArrayInputBytes(bytes));
var font = TrueTypeFontParser.Parse(input);
Assert.NotNull(font);
Assert.NotNull(font.TableRegister.NameTable);
Assert.NotEmpty(font.TableRegister.NameTable.NameRecords);
}
}
}

View File

@ -39,6 +39,7 @@
<ItemGroup>
<EmbeddedResource Remove="Fonts\TrueType\Andada-Regular.ttf" />
<EmbeddedResource Remove="Fonts\TrueType\google-simple-doc.ttf" />
<EmbeddedResource Remove="Fonts\TrueType\issue-258-corrupt-name-table.ttf" />
<EmbeddedResource Remove="Fonts\TrueType\PMingLiU.ttf" />
<EmbeddedResource Remove="Fonts\TrueType\Roboto-Regular.ttf" />
<EmbeddedResource Remove="Fonts\Type1\AdobeUtopia.pfa" />
@ -64,6 +65,9 @@
<Content Include="Fonts\TrueType\google-simple-doc.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Fonts\TrueType\issue-258-corrupt-name-table.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Fonts\TrueType\PMingLiU.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@ -688,6 +688,11 @@
return result;
}
if (offset == 0 && reference.Generation > ushort.MaxValue)
{
return new ObjectToken(offset, reference, NullToken.Instance);
}
Seek(offset);
if (!MoveNext())