Skip to content

Commit

Permalink
Merge pull request #8955 from brendandahl/issue7507
Browse files Browse the repository at this point in the history
Overwrite maxSizeOfInstructions in maxp with computed value.
  • Loading branch information
Snuffleupagus committed Sep 26, 2017
2 parents a1f5c26 + 18e2321 commit b837187
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 21 deletions.
67 changes: 46 additions & 21 deletions src/core/fonts.js
Expand Up @@ -1568,16 +1568,21 @@ var Font = (function FontClosure() {

function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart,
hintsValid) {
var glyphProfile = {
length: 0,
sizeOfInstructions: 0,
};
if (sourceEnd - sourceStart <= 12) {
// glyph with data less than 12 is invalid one
return 0;
return glyphProfile;
}
var glyf = source.subarray(sourceStart, sourceEnd);
var contoursCount = (glyf[0] << 8) | glyf[1];
if (contoursCount & 0x8000) {
// complex glyph, writing as is
dest.set(glyf, destStart);
return glyf.length;
glyphProfile.length = glyf.length;
return glyphProfile;
}

var i, j = 10, flagsCount = 0;
Expand All @@ -1589,6 +1594,7 @@ var Font = (function FontClosure() {
// skipping instructions
var instructionsStart = j;
var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
glyphProfile.sizeOfInstructions = instructionsLength;
j += 2 + instructionsLength;
var instructionsEnd = j;
// validating flags
Expand All @@ -1610,12 +1616,12 @@ var Font = (function FontClosure() {
}
// glyph without coordinates will be rejected
if (coordinatesLength === 0) {
return 0;
return glyphProfile;
}
var glyphDataLength = j + coordinatesLength;
if (glyphDataLength > glyf.length) {
// not enough data for coordinates
return 0;
return glyphProfile;
}
if (!hintsValid && instructionsLength > 0) {
dest.set(glyf.subarray(0, instructionsStart), destStart);
Expand All @@ -1626,17 +1632,20 @@ var Font = (function FontClosure() {
if (glyf.length - glyphDataLength > 3) {
glyphDataLength = (glyphDataLength + 3) & ~3;
}
return glyphDataLength;
glyphProfile.length = glyphDataLength;
return glyphProfile;
}
if (glyf.length - glyphDataLength > 3) {
// truncating and aligning to 4 bytes the long glyph data
glyphDataLength = (glyphDataLength + 3) & ~3;
dest.set(glyf.subarray(0, glyphDataLength), destStart);
return glyphDataLength;
glyphProfile.length = glyphDataLength;
return glyphProfile;
}
// glyph data is fine
dest.set(glyf, destStart);
return glyf.length;
glyphProfile.length = glyf.length;
return glyphProfile;
}

function sanitizeHead(head, numGlyphs, locaLength) {
Expand Down Expand Up @@ -1686,7 +1695,7 @@ var Font = (function FontClosure() {

function sanitizeGlyphLocations(loca, glyf, numGlyphs,
isGlyphLocationsLong, hintsValid,
dupFirstEntry) {
dupFirstEntry, maxSizeOfInstructions) {
var itemSize, itemDecode, itemEncode;
if (isGlyphLocationsLong) {
itemSize = 4;
Expand Down Expand Up @@ -1724,7 +1733,7 @@ var Font = (function FontClosure() {
var newGlyfData = new Uint8Array(oldGlyfDataLength);
var startOffset = itemDecode(locaData, 0);
var writeOffset = 0;
var missingGlyphData = Object.create(null);
var missingGlyphs = Object.create(null);
itemEncode(locaData, 0, writeOffset);
var i, j;
// When called with dupFirstEntry the number of glyphs has already been
Expand All @@ -1743,10 +1752,15 @@ var Font = (function FontClosure() {
startOffset = endOffset;
}

var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
newGlyfData, writeOffset, hintsValid);
var glyphProfile = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
newGlyfData, writeOffset,
hintsValid);
var newLength = glyphProfile.length;
if (newLength === 0) {
missingGlyphData[i] = true;
missingGlyphs[i] = true;
}
if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {
maxSizeOfInstructions = glyphProfile.sizeOfInstructions;
}
writeOffset += newLength;
itemEncode(locaData, j, writeOffset);
Expand All @@ -1762,10 +1776,7 @@ var Font = (function FontClosure() {
itemEncode(locaData, j, simpleGlyph.length);
}
glyf.data = simpleGlyph;
return missingGlyphData;
}

if (dupFirstEntry) {
} else if (dupFirstEntry) {
var firstEntryLength = itemDecode(locaData, itemSize);
if (newGlyfData.length > firstEntryLength + writeOffset) {
glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
Expand All @@ -1779,7 +1790,10 @@ var Font = (function FontClosure() {
} else {
glyf.data = newGlyfData.subarray(0, writeOffset);
}
return missingGlyphData;
return {
missingGlyphs,
maxSizeOfInstructions,
};
}

function readPostScriptTable(post, properties, maxpNumGlyphs) {
Expand Down Expand Up @@ -2226,6 +2240,7 @@ var Font = (function FontClosure() {
var version = font.getInt32();
var numGlyphs = font.getUint16();
var maxFunctionDefs = 0;
var maxSizeOfInstructions = 0;
if (version >= 0x00010000 && tables['maxp'].length >= 22) {
// maxZones can be invalid
font.pos += 8;
Expand All @@ -2236,6 +2251,8 @@ var Font = (function FontClosure() {
}
font.pos += 4;
maxFunctionDefs = font.getUint16();
font.pos += 6;
maxSizeOfInstructions = font.getUint16();
}

var dupFirstEntry = false;
Expand Down Expand Up @@ -2271,11 +2288,19 @@ var Font = (function FontClosure() {
if (isTrueType) {
var isGlyphLocationsLong = int16(tables['head'].data[50],
tables['head'].data[51]);
missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'],
numGlyphs, isGlyphLocationsLong,
hintsValid, dupFirstEntry);
}
var glyphsInfo = sanitizeGlyphLocations(tables['loca'], tables['glyf'],
numGlyphs, isGlyphLocationsLong,
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']) {
throw new FormatError('Required "hhea" table is not found');
}
Expand Down
1 change: 1 addition & 0 deletions test/pdfs/.gitignore
Expand Up @@ -40,6 +40,7 @@
!issue7446.pdf
!issue7492.pdf
!issue7544.pdf
!issue7507.pdf
!issue7580.pdf
!issue7598.pdf
!issue7665.pdf
Expand Down
Binary file added test/pdfs/issue7507.pdf
Binary file not shown.
7 changes: 7 additions & 0 deletions test/test_manifest.json
Expand Up @@ -684,6 +684,13 @@
"link": false,
"type": "load"
},
{ "id": "issue7507",
"file": "pdfs/issue7507.pdf",
"md5": "f7aeaafe0c89b94436e94eaa63307303",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "issue5501",
"file": "pdfs/issue5501.pdf",
"md5": "55a60699728fc92f491a2d7d490474e4",
Expand Down

0 comments on commit b837187

Please sign in to comment.