diff --git a/src/core/cff_parser.js b/src/core/cff_parser.js index c6655de89..2a8935dd8 100644 --- a/src/core/cff_parser.js +++ b/src/core/cff_parser.js @@ -787,6 +787,12 @@ class CFFParser { this.emptyPrivateDictionary(parentDict); return; } + // The Private DICT extends past the end of the font data, which means + // the embedded font is truncated; abort so the caller can substitute a + // system font instead of rendering blank glyphs (issue 7625). + if (offset + size > this.bytes.length) { + throw new FormatError("CFF Private DICT extends past end of font"); + } const privateDictEnd = offset + size; const dictData = this.bytes.subarray(offset, privateDictEnd); diff --git a/src/core/evaluator.js b/src/core/evaluator.js index d0cba1ddf..6961d2b00 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -4728,7 +4728,35 @@ class PartialEvaluator { const newProperties = await this.extractDataStructures(dict, properties); this.extractWidths(dict, descriptor, newProperties); - return new Font(fontName.name, fontFile, newProperties, this.options); + const font = new Font(fontName.name, fontFile, newProperties, this.options); + // The embedded font may have been too corrupt to parse, in which case + // we ended up in the fallback path without a substitution selected. + // Try the substitution map now so text renders in a font close to what + // the document asked for (issue 7625). + if ( + font.missingFile && + !font.systemFontInfo && + !isType3Font && + this.options.useSystemFonts + ) { + const standardFontName = getStandardFontName(fontName.name); + const substitution = getFontSubstitution( + this.systemFontCache, + this.idFactory, + this.options.standardFontDataUrl, + fontName.name, + standardFontName, + type + ); + if (substitution) { + if (substitution.guessFallback) { + substitution.guessFallback = false; + substitution.css += `,${font.fallbackName}`; + } + font.systemFontInfo = substitution; + } + } + return font; } static buildFontPaths(font, glyphs, handler, evaluatorOptions) { diff --git a/test/pdfs/issue7625.pdf.link b/test/pdfs/issue7625.pdf.link new file mode 100644 index 000000000..4d75563e8 --- /dev/null +++ b/test/pdfs/issue7625.pdf.link @@ -0,0 +1 @@ +https://github.com/mozilla/pdf.js/files/467169/Er.aestetik.en.loftestang.for.laering.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 8fc98c018..9c9153bdc 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -14310,5 +14310,15 @@ "md5": "39d15f7f810bd89a4e5858df9c75ca4e", "rounds": 1, "type": "eq" + }, + { + "id": "issue7625", + "file": "pdfs/issue7625.pdf", + "md5": "77ca0a41da767dca31ca45219e2ae202", + "link": true, + "rounds": 1, + "firstPage": 1, + "lastPage": 1, + "type": "eq" } ]