Sanitization of truetype fonts to fix #2537
This commit is contained in:
parent
0527b8bc8d
commit
e4c3b4501d
49
src/fonts.js
49
src/fonts.js
@ -3185,13 +3185,23 @@ var Font = (function FontClosure() {
|
||||
font.pos += header.length - 2;
|
||||
var numOfMetrics = int16(font.getBytes(2));
|
||||
|
||||
if (numOfMetrics > numGlyphs) {
|
||||
info('The numOfMetrics (' + numOfMetrics + ') should not be ' +
|
||||
'greater than the numGlyphs (' + numGlyphs + ')');
|
||||
// Reduce numOfMetrics if it is greater than numGlyphs
|
||||
numOfMetrics = numGlyphs;
|
||||
header.data[34] = (numOfMetrics & 0xff00) >> 8;
|
||||
header.data[35] = numOfMetrics & 0x00ff;
|
||||
}
|
||||
|
||||
var numOfSidebearings = numGlyphs - numOfMetrics;
|
||||
var numMissing = numOfSidebearings -
|
||||
((hmtx.length - numOfMetrics * 4) >> 1);
|
||||
((metrics.length - numOfMetrics * 4) >> 1);
|
||||
|
||||
if (numMissing > 0) {
|
||||
font.pos = (font.start ? font.start : 0) + metrics.offset;
|
||||
var entries = '';
|
||||
for (var i = 0, ii = hmtx.length; i < ii; i++)
|
||||
for (var i = 0, ii = metrics.length; i < ii; i++)
|
||||
entries += String.fromCharCode(font.getByte());
|
||||
for (var i = 0; i < numMissing; i++)
|
||||
entries += '\x00\x00';
|
||||
@ -3254,19 +3264,48 @@ var Font = (function FontClosure() {
|
||||
return glyf.length;
|
||||
}
|
||||
|
||||
function sanitizeHead(head) {
|
||||
function sanitizeHead(head, numGlyphs, locaLength) {
|
||||
var data = head.data;
|
||||
|
||||
// Validate version:
|
||||
// Should always be 0x00010000
|
||||
var version = int32([data[0], data[1], data[2], data[3]]);
|
||||
if (version >> 16 !== 1) {
|
||||
info('Invalid version in data type: ' + version);
|
||||
info('Attempting to fix invalid version in head table: ' + version);
|
||||
data[0] = 0;
|
||||
data[1] = 1;
|
||||
data[2] = 0;
|
||||
data[3] = 0;
|
||||
}
|
||||
|
||||
var indexToLocFormat = int16([data[50], data[51]]);
|
||||
if (indexToLocFormat < 0 || indexToLocFormat > 1) {
|
||||
info('Attempting to fix invalid indexToLocFormat in head table: ' +
|
||||
indexToLocFormat);
|
||||
|
||||
// The value of indexToLocFormat should be 0 if the loca table
|
||||
// consists of short offsets, and should be 1 if the loca table
|
||||
// consists of long offsets.
|
||||
//
|
||||
// The number of entries in the loca table should be numGlyphs + 1.
|
||||
//
|
||||
// Using this information, we can work backwards to deduce if the
|
||||
// size of each offset in the loca table, and thus figure out the
|
||||
// appropriate value for indexToLocFormat.
|
||||
|
||||
var numGlyphsPlusOne = numGlyphs + 1;
|
||||
if (locaLength === numGlyphsPlusOne << 1) {
|
||||
// 0x0000 indicates the loca table consists of short offsets
|
||||
data[50] = 0;
|
||||
data[51] = 0;
|
||||
} else if (locaLength === numGlyphsPlusOne << 2) {
|
||||
// 0x0001 indicates the loca table consists of long offsets
|
||||
data[50] = 0;
|
||||
data[51] = 1;
|
||||
} else {
|
||||
warn('Could not fix indexToLocFormat: ' + indexToLocFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeGlyphLocations(loca, glyf, numGlyphs,
|
||||
@ -3694,7 +3733,7 @@ var Font = (function FontClosure() {
|
||||
sanitizeTTPrograms(fpgm, prep);
|
||||
|
||||
if (head) {
|
||||
sanitizeHead(head);
|
||||
sanitizeHead(head, numGlyphs, loca.length);
|
||||
}
|
||||
|
||||
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
|
||||
|
1
test/pdfs/issue2537.pdf.link
Normal file
1
test/pdfs/issue2537.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://my.herk.ro/test.pdf
|
@ -35,7 +35,17 @@
|
||||
"md5": "c58e6642d8a6e2ddd5e07a543ef8f30d",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"pageLimit": 4,
|
||||
"firstPage": 4,
|
||||
"lastPage": 4,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue2537",
|
||||
"file": "pdfs/issue2537.pdf",
|
||||
"md5": "f56805a70ed3aa52aae5c16dd335f827",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"firstPage": 1,
|
||||
"lastPage": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "html5-canvas-cheat-sheet-load",
|
||||
|
Loading…
Reference in New Issue
Block a user