LibPDF: Don't crash on files with float CFF defaultWidthX

We'd unconditionally get the int from a Variant<int, float> here,
but PDFs often have a float for defaultWidthX and nominalWidthX.

Fixes crash opening Bakke2010a.pdf from pdffiles (but while the
file loads ok, it looks completely busted).
This commit is contained in:
Nico Weber 2023-10-12 11:25:16 -04:00 committed by Jelle Raaijmakers
parent e7c8ff3839
commit 349996f7f2
2 changed files with 15 additions and 6 deletions

View file

@ -41,8 +41,8 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
Vector<u8> encoding_codes;
auto charstrings_offset = 0;
Vector<ByteBuffer> subroutines;
int defaultWidthX = 0;
int nominalWidthX = 0;
float defaultWidthX = 0;
float nominalWidthX = 0;
TRY(parse_index(reader, [&](ReadonlyBytes const& element_data) {
Reader element_reader { element_data };
return parse_dict<TopDictOperator>(element_reader, [&](TopDictOperator op, Vector<DictOperand> const& operands) -> PDFErrorOr<void> {
@ -80,10 +80,12 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
break;
}
case PrivDictOperator::DefaultWidthX:
defaultWidthX = operands[0].get<int>();
if (!operands.is_empty())
defaultWidthX = to_number(operands[0]);
break;
case PrivDictOperator::NominalWidthX:
nominalWidthX = operands[0].get<int>();
if (!operands.is_empty())
nominalWidthX = to_number(operands[0]);
break;
}
return {};
@ -103,9 +105,9 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
// Adjust glyphs' widths as they are deltas from nominalWidthX
for (auto& glyph : glyphs) {
if (!glyph.has_width())
glyph.set_width(float(defaultWidthX));
glyph.set_width(defaultWidthX);
else
glyph.set_width(glyph.width() + float(nominalWidthX));
glyph.set_width(glyph.width() + nominalWidthX);
}
for (size_t i = 0; i < glyphs.size(); i++) {

View file

@ -56,6 +56,13 @@ public:
using SID = u16;
using DictOperand = Variant<int, float>;
static float to_number(DictOperand operand)
{
if (operand.has<int>())
return operand.get<int>();
return operand.get<float>();
}
static int load_int_dict_operand(u8 b0, Reader&);
static float load_float_dict_operand(Reader&);
static PDFErrorOr<DictOperand> load_dict_operand(u8, Reader&);