Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overwrite maxSizeOfInstructions in maxp with computed value. #8955

Merged
merged 1 commit into from
Sep 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 46 additions & 21 deletions src/core/fonts.js
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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