dotnet/wpf · error · FileFormatException
FileFormatException(SourceUri)
Error message
FileFormatException(SourceUri)
What it means
SetFace reads the sfnt offset table's numTables field and sanity-checks the file: its size must be at least the offset table plus numTables directory entries. When numTables is absurdly large relative to the file, the font is treated as malformed and FileFormatException(SourceUri) is thrown.
Solutions
- Replace the font file with a verified copy and confirm its byte size
- Catch FileFormatException around font loading and exclude the bad font
- Sanity-check the font before loading (file size > 12 bytes and header plausible)
- Scan deployment for partially-written font files
Example fix
// before
var fi = new FileInfo(path);
if (fi.Length == 0) throw ...;
driver.SetFace(0);
// after
var fi = new FileInfo(path);
if (fi.Length < 12) throw new IOException($"Font file too small: {path}");
driver.SetFace(0); Defensive patterns
Strategy: try-catch
Validate before calling
long minSize = 12; // offset table only; full check needs numTables
if (stream.Length < minSize) throw new IOException("Font file too small"); Try / catch
try { driver.SetFace(0); }
catch (FileFormatException e)
{
log.Error($"Malformed font header in {e.SourceUri}");
ExcludeFont(path);
} Prevention
- Validate font files with a font tool before shipping them
- Detect partially-written files (compare to manifest sizes)
- Treat fonts from untrusted sources as suspect and pre-validate
When it happens
Trigger: Calling SetFace (or ComputeSubset) on a font whose binary header reports a numTables count inconsistent with the actual stream length — typical of corrupt, truncated, or counterfeit font files.
Common situations: Damaged .ttf/.ttc after a bad transfer, fuzzed/hostile font inputs, testing the font pipeline with random bytes, fonts stored inside archives that were extracted incompletely.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- FileFormatException(SourceUri, e)
- Count must be 1 when CommitPolicies is set to…
- FileFormatException
- FileFormatException
- FileFormatException(new Uri(fileName…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/25936db13ca2332f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontFace/FontDriver.cs:188
seekPosition += (4 + 4 + 4 * faceIndex);
_directoryOffset = ReadOpenTypeLong(seekPosition);
seekPosition = _fileStream + (_directoryOffset + 4);
// 4 means that we skip the version number
}
_faceIndex = faceIndex;
int numTables = ReadOpenTypeUShort(seekPosition);
seekPosition += 2;
// quick check for malformed fonts, see if numTables is too large
// file size should be >= sizeof(offset table) + numTables * (sizeof(directory entry) + minimum table size (4))
long minimumFileSize = (4 + 2 + 2 + 2 + 2) + numTables * (4 + 4 + 4 + 4 + 4);
if (_fileStream.Size < minimumFileSize)
{
throw new FileFormatException(SourceUri);
}
_tableDirectory = new DirectoryEntry[numTables];
// skip searchRange, entrySelector and rangeShift
seekPosition += 6;
// I can't use foreach here because C# disallows modifying the current value
for (int i = 0; i < _tableDirectory.Length; ++i)
{
_tableDirectory[i].tag = (TrueTypeTags)ReadOpenTypeLong(seekPosition);
seekPosition += 8; // skip checksum
int offset = ReadOpenTypeLong(seekPosition);
seekPosition += 4;
int length = ReadOpenTypeLong(seekPosition);
seekPosition += 4;
_tableDirectory[i].pointer = _fileStream.CheckedProbe(offset, length);View on GitHub (pinned to 81131a70a4)