Merge pull request #7361 from Snuffleupagus/bug-1146106

Attempt to recover valid `format 3` FDSelect data from broken CFF fonts (bug 1146106)
This commit is contained in:
Brendan Dahl 2016-06-07 11:47:51 -07:00
commit c4db4dd4ac
5 changed files with 54 additions and 12 deletions

View File

@ -856,8 +856,8 @@ var CFFParser = (function CFFParserClosure() {
var start = pos; var start = pos;
var bytes = this.bytes; var bytes = this.bytes;
var format = bytes[pos++]; var format = bytes[pos++];
var fdSelect = []; var fdSelect = [], rawBytes;
var i; var i, invalidFirstGID = false;
switch (format) { switch (format) {
case 0: case 0:
@ -865,11 +865,18 @@ var CFFParser = (function CFFParserClosure() {
var id = bytes[pos++]; var id = bytes[pos++];
fdSelect.push(id); fdSelect.push(id);
} }
rawBytes = bytes.subarray(start, pos);
break; break;
case 3: case 3:
var rangesCount = (bytes[pos++] << 8) | bytes[pos++]; var rangesCount = (bytes[pos++] << 8) | bytes[pos++];
for (i = 0; i < rangesCount; ++i) { for (i = 0; i < rangesCount; ++i) {
var first = (bytes[pos++] << 8) | bytes[pos++]; var first = (bytes[pos++] << 8) | bytes[pos++];
if (i === 0 && first !== 0) {
warn('parseFDSelect: The first range must have a first GID of 0' +
' -- trying to recover.');
invalidFirstGID = true;
first = 0;
}
var fdIndex = bytes[pos++]; var fdIndex = bytes[pos++];
var next = (bytes[pos] << 8) | bytes[pos + 1]; var next = (bytes[pos] << 8) | bytes[pos + 1];
for (var j = first; j < next; ++j) { for (var j = first; j < next; ++j) {
@ -878,13 +885,19 @@ var CFFParser = (function CFFParserClosure() {
} }
// Advance past the sentinel(next). // Advance past the sentinel(next).
pos += 2; pos += 2;
rawBytes = bytes.subarray(start, pos);
if (invalidFirstGID) {
rawBytes[3] = rawBytes[4] = 0; // Adjust the first range, first GID.
}
break; break;
default: default:
error('Unknown fdselect format ' + format); error('parseFDSelect: Unknown format "' + format + '".');
break; break;
} }
var end = pos; assert(fdSelect.length === length, 'parseFDSelect: Invalid font data.');
return new CFFFDSelect(fdSelect, bytes.subarray(start, end));
return new CFFFDSelect(fdSelect, rawBytes);
} }
}; };
return CFFParser; return CFFParser;

View File

@ -37,6 +37,7 @@
!bug1050040.pdf !bug1050040.pdf
!bug1200096.pdf !bug1200096.pdf
!bug1068432.pdf !bug1068432.pdf
!bug1146106.pdf
!issue5564_reduced.pdf !issue5564_reduced.pdf
!canvas.pdf !canvas.pdf
!bug1132849.pdf !bug1132849.pdf

BIN
test/pdfs/bug1146106.pdf Normal file

Binary file not shown.

View File

@ -210,6 +210,13 @@
"link": false, "link": false,
"type": "eq" "type": "eq"
}, },
{ "id": "bug1146106",
"file": "pdfs/bug1146106.pdf",
"md5": "a323d3766da49ee40f7d5dff0aeb0cc1",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "issue1512", { "id": "issue1512",
"file": "pdfs/issue1512r.pdf", "file": "pdfs/issue1512r.pdf",
"md5": "af48ede2658d99cca423147085c6609b", "md5": "af48ede2658d99cca423147085c6609b",

View File

@ -262,10 +262,12 @@ describe('CFFParser', function() {
var bytes = new Uint8Array([0x00, // format var bytes = new Uint8Array([0x00, // format
0x00, // gid: 0 fd: 0 0x00, // gid: 0 fd: 0
0x01 // gid: 1 fd: 1 0x01 // gid: 1 fd: 1
]); ]);
parser.bytes = bytes; parser.bytes = bytes.slice();
var fdSelect = parser.parseFDSelect(0, 2); var fdSelect = parser.parseFDSelect(0, 2);
expect(fdSelect.fdSelect).toEqual([0, 1]); expect(fdSelect.fdSelect).toEqual([0, 1]);
expect(fdSelect.raw).toEqual(bytes);
}); });
it('parses fdselect format 3', function() { it('parses fdselect format 3', function() {
@ -273,13 +275,32 @@ describe('CFFParser', function() {
0x00, 0x02, // range count 0x00, 0x02, // range count
0x00, 0x00, // first gid 0x00, 0x00, // first gid
0x09, // font dict 1 id 0x09, // font dict 1 id
0x00, 0x02, // nex gid 0x00, 0x02, // next gid
0x0a, // font dict 2 gid 0x0a, // font dict 2 id
0x00, 0x04 // sentinel (last gid) 0x00, 0x04 // sentinel (last gid)
]); ]);
parser.bytes = bytes; parser.bytes = bytes.slice();
var fdSelect = parser.parseFDSelect(0, 2); var fdSelect = parser.parseFDSelect(0, 4);
expect(fdSelect.fdSelect).toEqual([9, 9, 0xa, 0xa]); expect(fdSelect.fdSelect).toEqual([9, 9, 0xa, 0xa]);
expect(fdSelect.raw).toEqual(bytes);
});
it('parses invalid fdselect format 3 (bug 1146106)', function() {
var bytes = new Uint8Array([0x03, // format
0x00, 0x02, // range count
0x00, 0x01, // first gid (invalid)
0x09, // font dict 1 id
0x00, 0x02, // next gid
0x0a, // font dict 2 id
0x00, 0x04 // sentinel (last gid)
]);
parser.bytes = bytes.slice();
var fdSelect = parser.parseFDSelect(0, 4);
expect(fdSelect.fdSelect).toEqual([9, 9, 0xa, 0xa]);
bytes[3] = bytes[4] = 0x00; // The adjusted first range, first gid.
expect(fdSelect.raw).toEqual(bytes);
}); });
// TODO fdArray // TODO fdArray