LibPDF: Support offset size 3 in CFF index reading

...and replace template instantiations with a loop, to make this
easily possible.

Vaguely nice for code size as well.

Needed for example in 0000054.pdf and 0000354.pdf in 0000.zip in the
pdfa dataset.
This commit is contained in:
Nico Weber 2023-10-22 22:57:27 -04:00 committed by Tim Flynn
parent 3197f0cab6
commit 58ff7b5336
Notes: sideshowbarker 2024-07-17 07:38:17 +09:00
2 changed files with 20 additions and 20 deletions

View file

@ -874,26 +874,31 @@ PDFErrorOr<void> CFF::parse_index(Reader& reader, IndexDataHandler&& data_handle
if (count == 0)
return {};
auto offset_size = TRY(reader.try_read<OffSize>());
if (offset_size == 1)
return parse_index_data<u8>(count, reader, data_handler);
if (offset_size == 2)
return parse_index_data<u16>(count, reader, data_handler);
if (offset_size == 4)
return parse_index_data<u32>(count, reader, data_handler);
VERIFY_NOT_REACHED();
if (offset_size > 4)
return error("CFF INDEX Data offset_size > 4 not supported");
return parse_index_data(offset_size, count, reader, data_handler);
}
template<typename OffsetType>
PDFErrorOr<void> CFF::parse_index_data(Card16 count, Reader& reader, IndexDataHandler& handler)
PDFErrorOr<void> CFF::parse_index_data(OffSize offset_size, Card16 count, Reader& reader, IndexDataHandler& handler)
{
// CFF spec, "5 INDEX Data"
OffsetType last_data_end = 1;
auto offset_refpoint = reader.offset() + sizeof(OffsetType) * (count + 1) - 1;
u32 last_data_end = 1;
auto read_offset = [&]() -> PDFErrorOr<u32> {
u32 offset = 0;
for (OffSize i = 0; i < offset_size; ++i)
offset = (offset << 8) | TRY(reader.try_read<u8>());
return offset;
};
auto offset_refpoint = reader.offset() + offset_size * (count + 1) - 1;
for (u16 i = 0; i < count; i++) {
reader.save();
reader.move_by(sizeof(OffsetType) * i);
OffsetType data_start = reader.read<BigEndian<OffsetType>>();
last_data_end = reader.read<BigEndian<OffsetType>>();
reader.move_by(offset_size * i);
u32 data_start = TRY(read_offset());
last_data_end = TRY(read_offset());
auto data_size = last_data_end - data_start;
reader.move_to(offset_refpoint + data_start);
TRY(handler(reader.bytes().slice(reader.offset(), data_size)));
@ -903,10 +908,6 @@ PDFErrorOr<void> CFF::parse_index_data(Card16 count, Reader& reader, IndexDataHa
return {};
}
template PDFErrorOr<void> CFF::parse_index_data<u8>(Card16, Reader&, IndexDataHandler&);
template PDFErrorOr<void> CFF::parse_index_data<u16>(Card16, Reader&, IndexDataHandler&);
template PDFErrorOr<void> CFF::parse_index_data<u32>(Card16, Reader&, IndexDataHandler&);
int CFF::load_int_dict_operand(u8 b0, Reader& reader)
{
// CFF spec, "Table 3 Operand Encoding"

View file

@ -81,8 +81,7 @@ public:
using IndexDataHandler = Function<PDFErrorOr<void>(ReadonlyBytes const&)>;
static PDFErrorOr<void> parse_index(Reader& reader, IndexDataHandler&&);
template<typename OffsetType>
static PDFErrorOr<void> parse_index_data(Card16 count, Reader& reader, IndexDataHandler&);
static PDFErrorOr<void> parse_index_data(OffSize offset_size, Card16 count, Reader& reader, IndexDataHandler&);
template<typename OperatorT>
using DictEntryHandler = Function<PDFErrorOr<void>(OperatorT, Vector<DictOperand> const&)>;