Merge pull request #8955 from brendandahl/issue7507

Overwrite maxSizeOfInstructions in maxp with computed value.
This commit is contained in:
Jonas Jenwald 2017-09-26 14:16:56 +02:00 committed by GitHub
commit b837187094
4 changed files with 54 additions and 21 deletions

View File

@ -1568,16 +1568,21 @@ var Font = (function FontClosure() {
function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart,
hintsValid) { hintsValid) {
var glyphProfile = {
length: 0,
sizeOfInstructions: 0,
};
if (sourceEnd - sourceStart <= 12) { if (sourceEnd - sourceStart <= 12) {
// glyph with data less than 12 is invalid one // glyph with data less than 12 is invalid one
return 0; return glyphProfile;
} }
var glyf = source.subarray(sourceStart, sourceEnd); var glyf = source.subarray(sourceStart, sourceEnd);
var contoursCount = (glyf[0] << 8) | glyf[1]; var contoursCount = (glyf[0] << 8) | glyf[1];
if (contoursCount & 0x8000) { if (contoursCount & 0x8000) {
// complex glyph, writing as is // complex glyph, writing as is
dest.set(glyf, destStart); dest.set(glyf, destStart);
return glyf.length; glyphProfile.length = glyf.length;
return glyphProfile;
} }
var i, j = 10, flagsCount = 0; var i, j = 10, flagsCount = 0;
@ -1589,6 +1594,7 @@ var Font = (function FontClosure() {
// skipping instructions // skipping instructions
var instructionsStart = j; var instructionsStart = j;
var instructionsLength = (glyf[j] << 8) | glyf[j + 1]; var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
glyphProfile.sizeOfInstructions = instructionsLength;
j += 2 + instructionsLength; j += 2 + instructionsLength;
var instructionsEnd = j; var instructionsEnd = j;
// validating flags // validating flags
@ -1610,12 +1616,12 @@ var Font = (function FontClosure() {
} }
// glyph without coordinates will be rejected // glyph without coordinates will be rejected
if (coordinatesLength === 0) { if (coordinatesLength === 0) {
return 0; return glyphProfile;
} }
var glyphDataLength = j + coordinatesLength; var glyphDataLength = j + coordinatesLength;
if (glyphDataLength > glyf.length) { if (glyphDataLength > glyf.length) {
// not enough data for coordinates // not enough data for coordinates
return 0; return glyphProfile;
} }
if (!hintsValid && instructionsLength > 0) { if (!hintsValid && instructionsLength > 0) {
dest.set(glyf.subarray(0, instructionsStart), destStart); dest.set(glyf.subarray(0, instructionsStart), destStart);
@ -1626,17 +1632,20 @@ var Font = (function FontClosure() {
if (glyf.length - glyphDataLength > 3) { if (glyf.length - glyphDataLength > 3) {
glyphDataLength = (glyphDataLength + 3) & ~3; glyphDataLength = (glyphDataLength + 3) & ~3;
} }
return glyphDataLength; glyphProfile.length = glyphDataLength;
return glyphProfile;
} }
if (glyf.length - glyphDataLength > 3) { if (glyf.length - glyphDataLength > 3) {
// truncating and aligning to 4 bytes the long glyph data // truncating and aligning to 4 bytes the long glyph data
glyphDataLength = (glyphDataLength + 3) & ~3; glyphDataLength = (glyphDataLength + 3) & ~3;
dest.set(glyf.subarray(0, glyphDataLength), destStart); dest.set(glyf.subarray(0, glyphDataLength), destStart);
return glyphDataLength; glyphProfile.length = glyphDataLength;
return glyphProfile;
} }
// glyph data is fine // glyph data is fine
dest.set(glyf, destStart); dest.set(glyf, destStart);
return glyf.length; glyphProfile.length = glyf.length;
return glyphProfile;
} }
function sanitizeHead(head, numGlyphs, locaLength) { function sanitizeHead(head, numGlyphs, locaLength) {
@ -1686,7 +1695,7 @@ var Font = (function FontClosure() {
function sanitizeGlyphLocations(loca, glyf, numGlyphs, function sanitizeGlyphLocations(loca, glyf, numGlyphs,
isGlyphLocationsLong, hintsValid, isGlyphLocationsLong, hintsValid,
dupFirstEntry) { dupFirstEntry, maxSizeOfInstructions) {
var itemSize, itemDecode, itemEncode; var itemSize, itemDecode, itemEncode;
if (isGlyphLocationsLong) { if (isGlyphLocationsLong) {
itemSize = 4; itemSize = 4;
@ -1724,7 +1733,7 @@ var Font = (function FontClosure() {
var newGlyfData = new Uint8Array(oldGlyfDataLength); var newGlyfData = new Uint8Array(oldGlyfDataLength);
var startOffset = itemDecode(locaData, 0); var startOffset = itemDecode(locaData, 0);
var writeOffset = 0; var writeOffset = 0;
var missingGlyphData = Object.create(null); var missingGlyphs = Object.create(null);
itemEncode(locaData, 0, writeOffset); itemEncode(locaData, 0, writeOffset);
var i, j; var i, j;
// When called with dupFirstEntry the number of glyphs has already been // When called with dupFirstEntry the number of glyphs has already been
@ -1743,10 +1752,15 @@ var Font = (function FontClosure() {
startOffset = endOffset; startOffset = endOffset;
} }
var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, var glyphProfile = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
newGlyfData, writeOffset, hintsValid); newGlyfData, writeOffset,
hintsValid);
var newLength = glyphProfile.length;
if (newLength === 0) { if (newLength === 0) {
missingGlyphData[i] = true; missingGlyphs[i] = true;
}
if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {
maxSizeOfInstructions = glyphProfile.sizeOfInstructions;
} }
writeOffset += newLength; writeOffset += newLength;
itemEncode(locaData, j, writeOffset); itemEncode(locaData, j, writeOffset);
@ -1762,10 +1776,7 @@ var Font = (function FontClosure() {
itemEncode(locaData, j, simpleGlyph.length); itemEncode(locaData, j, simpleGlyph.length);
} }
glyf.data = simpleGlyph; glyf.data = simpleGlyph;
return missingGlyphData; } else if (dupFirstEntry) {
}
if (dupFirstEntry) {
var firstEntryLength = itemDecode(locaData, itemSize); var firstEntryLength = itemDecode(locaData, itemSize);
if (newGlyfData.length > firstEntryLength + writeOffset) { if (newGlyfData.length > firstEntryLength + writeOffset) {
glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
@ -1779,7 +1790,10 @@ var Font = (function FontClosure() {
} else { } else {
glyf.data = newGlyfData.subarray(0, writeOffset); glyf.data = newGlyfData.subarray(0, writeOffset);
} }
return missingGlyphData; return {
missingGlyphs,
maxSizeOfInstructions,
};
} }
function readPostScriptTable(post, properties, maxpNumGlyphs) { function readPostScriptTable(post, properties, maxpNumGlyphs) {
@ -2226,6 +2240,7 @@ var Font = (function FontClosure() {
var version = font.getInt32(); var version = font.getInt32();
var numGlyphs = font.getUint16(); var numGlyphs = font.getUint16();
var maxFunctionDefs = 0; var maxFunctionDefs = 0;
var maxSizeOfInstructions = 0;
if (version >= 0x00010000 && tables['maxp'].length >= 22) { if (version >= 0x00010000 && tables['maxp'].length >= 22) {
// maxZones can be invalid // maxZones can be invalid
font.pos += 8; font.pos += 8;
@ -2236,6 +2251,8 @@ var Font = (function FontClosure() {
} }
font.pos += 4; font.pos += 4;
maxFunctionDefs = font.getUint16(); maxFunctionDefs = font.getUint16();
font.pos += 6;
maxSizeOfInstructions = font.getUint16();
} }
var dupFirstEntry = false; var dupFirstEntry = false;
@ -2271,11 +2288,19 @@ var Font = (function FontClosure() {
if (isTrueType) { if (isTrueType) {
var isGlyphLocationsLong = int16(tables['head'].data[50], var isGlyphLocationsLong = int16(tables['head'].data[50],
tables['head'].data[51]); tables['head'].data[51]);
missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'], var glyphsInfo = sanitizeGlyphLocations(tables['loca'], tables['glyf'],
numGlyphs, isGlyphLocationsLong, numGlyphs, isGlyphLocationsLong,
hintsValid, dupFirstEntry); hintsValid, dupFirstEntry,
} maxSizeOfInstructions);
missingGlyphs = glyphsInfo.missingGlyphs;
// Some fonts have incorrect maxSizeOfInstructions values, so we use
// the computed value instead.
if (version >= 0x00010000 && tables['maxp'].length >= 22) {
tables['maxp'].data[26] = glyphsInfo.maxSizeOfInstructions >> 8;
tables['maxp'].data[27] = glyphsInfo.maxSizeOfInstructions & 255;
}
}
if (!tables['hhea']) { if (!tables['hhea']) {
throw new FormatError('Required "hhea" table is not found'); throw new FormatError('Required "hhea" table is not found');
} }

View File

@ -40,6 +40,7 @@
!issue7446.pdf !issue7446.pdf
!issue7492.pdf !issue7492.pdf
!issue7544.pdf !issue7544.pdf
!issue7507.pdf
!issue7580.pdf !issue7580.pdf
!issue7598.pdf !issue7598.pdf
!issue7665.pdf !issue7665.pdf

BIN
test/pdfs/issue7507.pdf Normal file

Binary file not shown.

View File

@ -684,6 +684,13 @@
"link": false, "link": false,
"type": "load" "type": "load"
}, },
{ "id": "issue7507",
"file": "pdfs/issue7507.pdf",
"md5": "f7aeaafe0c89b94436e94eaa63307303",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "issue5501", { "id": "issue5501",
"file": "pdfs/issue5501.pdf", "file": "pdfs/issue5501.pdf",
"md5": "55a60699728fc92f491a2d7d490474e4", "md5": "55a60699728fc92f491a2d7d490474e4",