Prevent the deprecated 'dotsection' command in Type1C to hit the sanitizer
This commit is contained in:
parent
7fa63e68dd
commit
bcd8619414
37
fonts.js
37
fonts.js
@ -2251,7 +2251,7 @@ var Type2CFF = (function() {
|
|||||||
|
|
||||||
var strings = this.getStrings(stringIndex);
|
var strings = this.getStrings(stringIndex);
|
||||||
|
|
||||||
var baseDict = this.parseDict(dictIndex.get(0));
|
var baseDict = this.parseDict(dictIndex.get(0).data);
|
||||||
var topDict = this.getTopDict(baseDict, strings);
|
var topDict = this.getTopDict(baseDict, strings);
|
||||||
|
|
||||||
var bytes = this.bytes;
|
var bytes = this.bytes;
|
||||||
@ -2276,6 +2276,33 @@ var Type2CFF = (function() {
|
|||||||
if (hasSupplement)
|
if (hasSupplement)
|
||||||
bytes[topDict.Encoding] = 0;
|
bytes[topDict.Encoding] = 0;
|
||||||
|
|
||||||
|
// The CFF specification state that the 'dotsection' command
|
||||||
|
// (12, 0) is deprecated and treated as a no-op, but all Type2
|
||||||
|
// charstrings processors should support them. Unfortunately
|
||||||
|
// the font sanitizer don't. As a workaround the sequence (12, 0)
|
||||||
|
// is replaced by a useless (0, hmoveto).
|
||||||
|
var count = charStrings.length;
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
var charstring = charStrings.get(i);
|
||||||
|
|
||||||
|
var start = charstring.start;
|
||||||
|
var data = charstring.data;
|
||||||
|
var length = data.length;
|
||||||
|
for (var j = 0; j <= length; j) {
|
||||||
|
var value = data[j++];
|
||||||
|
if (value == 12 && data[j++] == 0) {
|
||||||
|
bytes[start + j - 2] = 139;
|
||||||
|
bytes[start + j - 1] = 22;
|
||||||
|
} else if (value === 28) {
|
||||||
|
j += 2;
|
||||||
|
} else if (value >= 247 && value <= 254) {
|
||||||
|
j++;
|
||||||
|
} else if (value == 255) {
|
||||||
|
j += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// charstrings contains info about glyphs (one element per glyph
|
// charstrings contains info about glyphs (one element per glyph
|
||||||
// containing mappings for {unicode, width})
|
// containing mappings for {unicode, width})
|
||||||
var charstrings = this.getCharStrings(charset, charStrings,
|
var charstrings = this.getCharStrings(charset, charStrings,
|
||||||
@ -2566,7 +2593,7 @@ var Type2CFF = (function() {
|
|||||||
} else if (value <= 254) {
|
} else if (value <= 254) {
|
||||||
return -((value - 251) * 256) - dict[pos++] - 108;
|
return -((value - 251) * 256) - dict[pos++] - 108;
|
||||||
} else {
|
} else {
|
||||||
error('Incorrect byte');
|
error('255 is not a valid DICT command');
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
@ -2644,7 +2671,11 @@ var Type2CFF = (function() {
|
|||||||
|
|
||||||
var start = offsets[index];
|
var start = offsets[index];
|
||||||
var end = offsets[index + 1];
|
var end = offsets[index + 1];
|
||||||
return bytes.subarray(start, end);
|
return {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
data: bytes.subarray(start, end)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
length: count,
|
length: count,
|
||||||
endPos: end
|
endPos: end
|
||||||
|
@ -560,7 +560,7 @@ var CFFDictDataMap = {
|
|||||||
'18': {
|
'18': {
|
||||||
name: 'ExpansionFactor'
|
name: 'ExpansionFactor'
|
||||||
},
|
},
|
||||||
'9': {
|
'19': {
|
||||||
name: 'initialRandomSeed'
|
name: 'initialRandomSeed'
|
||||||
},
|
},
|
||||||
'20': {
|
'20': {
|
||||||
|
@ -20,17 +20,27 @@ function readCharset(aStream, aCharstrings) {
|
|||||||
var charset = {};
|
var charset = {};
|
||||||
|
|
||||||
var format = aStream.getByte();
|
var format = aStream.getByte();
|
||||||
|
var count = aCharstrings.length - 1;
|
||||||
if (format == 0) {
|
if (format == 0) {
|
||||||
charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
|
charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
|
||||||
|
|
||||||
var count = aCharstrings.length - 1;
|
|
||||||
for (var i = 1; i < count + 1; i++) {
|
for (var i = 1; i < count + 1; i++) {
|
||||||
var sid = aStream.getByte() << 8 | aStream.getByte();
|
var sid = aStream.getByte() << 8 | aStream.getByte();
|
||||||
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
||||||
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
||||||
}
|
}
|
||||||
} else if (format == 1) {
|
} else if (format == 1) {
|
||||||
error('Charset Range are not supported');
|
for (var i = 1; i < count + 1; i++) {
|
||||||
|
var first = aStream.getByte();
|
||||||
|
first = (first << 8) | aStream.getByte();
|
||||||
|
var numLeft = aStream.getByte();
|
||||||
|
for (var j = 0; j <= numLeft; j++) {
|
||||||
|
var sid = first++;
|
||||||
|
if (CFFStrings[sid] == 'three')
|
||||||
|
log(aCharstrings[j]);
|
||||||
|
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error('Invalid charset format');
|
error('Invalid charset format');
|
||||||
}
|
}
|
||||||
@ -44,6 +54,9 @@ function readCharset(aStream, aCharstrings) {
|
|||||||
* chapter 3.1.
|
* chapter 3.1.
|
||||||
*/
|
*/
|
||||||
function readCharstringEncoding(aString) {
|
function readCharstringEncoding(aString) {
|
||||||
|
if (!aString)
|
||||||
|
return "";
|
||||||
|
|
||||||
var charstringTokens = [];
|
var charstringTokens = [];
|
||||||
|
|
||||||
var count = aString.length;
|
var count = aString.length;
|
||||||
@ -71,9 +84,9 @@ function readCharstringEncoding(aString) {
|
|||||||
} else if (value < 247) {
|
} else if (value < 247) {
|
||||||
token = parseInt(value) - 139;
|
token = parseInt(value) - 139;
|
||||||
} else if (value < 251) {
|
} else if (value < 251) {
|
||||||
token = ((value - 247) * 256) + aString[i++] + 108;
|
token = (value - 247) * 256 + aString[i++] + 108;
|
||||||
} else if (value < 255) {
|
} else if (value < 255) {
|
||||||
token = -((value - 251) * 256) - aString[i++] - 108;
|
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||||
} else {// value == 255
|
} else {// value == 255
|
||||||
token = aString[i++] << 24 | aString[i++] << 16 |
|
token = aString[i++] << 24 | aString[i++] << 16 |
|
||||||
aString[i++] << 8 | aString[i];
|
aString[i++] << 8 | aString[i];
|
||||||
@ -146,9 +159,9 @@ function readFontDictData(aString, aMap) {
|
|||||||
} else if (value <= 246) {
|
} else if (value <= 246) {
|
||||||
token = parseInt(value) - 139;
|
token = parseInt(value) - 139;
|
||||||
} else if (value <= 250) {
|
} else if (value <= 250) {
|
||||||
token = ((value - 247) * 256) + aString[i++] + 108;
|
token = (value - 247) * 256 + aString[i++] + 108;
|
||||||
} else if (value <= 254) {
|
} else if (value <= 254) {
|
||||||
token = -((value - 251) * 256) - aString[i++] - 108;
|
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||||
} else if (value == 255) {
|
} else if (value == 255) {
|
||||||
error('255 is not a valid DICT command');
|
error('255 is not a valid DICT command');
|
||||||
}
|
}
|
||||||
@ -199,7 +212,7 @@ function readFontIndexData(aStream, aIsByte) {
|
|||||||
for (var i = 0; i < count + 1; i++)
|
for (var i = 0; i < count + 1; i++)
|
||||||
offsets.push(getNextOffset());
|
offsets.push(getNextOffset());
|
||||||
|
|
||||||
log('Found ' + count + ' objects at offsets :' +
|
dump('Found ' + count + ' objects at offsets :' +
|
||||||
offsets + ' (offsize: ' + offsize + ')');
|
offsets + ' (offsize: ' + offsize + ')');
|
||||||
|
|
||||||
// Now extract the objects
|
// Now extract the objects
|
||||||
@ -285,23 +298,20 @@ var Type2Parser = function(aFilePath) {
|
|||||||
font.set('hdrSize', aStream.getByte());
|
font.set('hdrSize', aStream.getByte());
|
||||||
font.set('offsize', aStream.getByte());
|
font.set('offsize', aStream.getByte());
|
||||||
|
|
||||||
// Move the cursor after the header
|
|
||||||
aStream.skip(font.get('hdrSize') - aStream.pos);
|
|
||||||
|
|
||||||
// Read the NAME Index
|
// Read the NAME Index
|
||||||
dump('Reading Index: Names');
|
dump('Reading Index: Names');
|
||||||
font.set('Names', readFontIndexData(aStream));
|
font.set('Names', readFontIndexData(aStream));
|
||||||
log('Names: ' + font.get('Names'));
|
dump('Names: ' + font.get('Names'));
|
||||||
|
|
||||||
// Read the Top Dict Index
|
// Read the Top Dict Index
|
||||||
dump('Reading Index: TopDict');
|
dump('Reading Index: TopDict');
|
||||||
var topDict = readFontIndexData(aStream, true);
|
var topDict = readFontIndexData(aStream, true);
|
||||||
log('TopDict: ' + topDict);
|
dump('TopDict: ' + topDict);
|
||||||
|
|
||||||
// Read the String Index
|
// Read the String Index
|
||||||
dump('Reading Index: Strings');
|
dump('Reading Index: Strings');
|
||||||
var strings = readFontIndexData(aStream);
|
var strings = readFontIndexData(aStream);
|
||||||
log('strings: ' + strings);
|
dump('strings: ' + strings);
|
||||||
|
|
||||||
// Fill up the Strings dictionary with the new unique strings
|
// Fill up the Strings dictionary with the new unique strings
|
||||||
for (var i = 0; i < strings.length; i++)
|
for (var i = 0; i < strings.length; i++)
|
||||||
@ -321,7 +331,7 @@ var Type2Parser = function(aFilePath) {
|
|||||||
|
|
||||||
// Reading Private Dict
|
// Reading Private Dict
|
||||||
var priv = font.get('Private');
|
var priv = font.get('Private');
|
||||||
log('Reading Private Dict (offset: ' + priv.offset +
|
dump('Reading Private Dict (offset: ' + priv.offset +
|
||||||
' size: ' + priv.size + ')');
|
' size: ' + priv.size + ')');
|
||||||
aStream.pos = priv.offset;
|
aStream.pos = priv.offset;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user