LibPDF: Do not crash on invalid page drawing operators

Lets us no longer crash rendering page 2 of
BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf.

Test file hand-written (based on text.pdf) and offsets fixed up
with `mutool clean` as usual.
This commit is contained in:
Nico Weber committed 2026-07-29 09:11:03 -04:00
1 parent 90fb619ca4
commit b58497421f
5 files changed
+58 -4

No files matched your search

+1
View File
@@ -14,6 +14,7 @@ set(TEST_FILES
encoding.pdf
encryption_nocopy.pdf
group.pdf
invalid-operator.pdf
jbig2-globals.pdf
jbig2-globals-indirect-reference.pdf
jpeg2000-indexed-small.pdf
+14
View File
@@ -141,6 +141,20 @@ TEST_CASE(resolve_indirect_reference_during_parsing)
EXPECT_EQ(jbig2_stream->bytes().size(), 20'000U);
}
TEST_CASE(invalid_operator)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map("invalid-operator.pdf"sv));
auto document = MUST(PDF::Document::create(file->bytes()));
MUST(document->initialize());
EXPECT_EQ(document->get_page_count(), 1U);
auto page = MUST(document->get_page(0));
auto page_size = Gfx::IntSize { 612, 792 };
auto bitmap = TRY_OR_FAIL(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, page_size));
auto result = PDF::Renderer::render(document, page, bitmap, Color::White, PDF::RenderingPreferences {});
// Shouldn't crash.
}
TEST_CASE(jbig2_embedded_organization_cross_chunk_reference)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map("jbig2-globals.pdf"sv));
+37
View File
@@ -0,0 +1,37 @@
%PDF-1.3
%µ¶
1 0 obj
<</Type/Catalog/Pages 2 0 R>>
endobj
2 0 obj
<</Type/Pages/Kids[3 0 R]/Count 1>>
endobj
3 0 obj
<</Type/Page/Parent 2 0 R/MediaBox[0 0 525 250]/Contents 4 0 R>>
endobj
4 0 obj
<</Length 5>>
stream
q
QQ
endstream
endobj
xref
0 5
0000000000 65536 f
0000000016 00000 n
0000000062 00000 n
0000000114 00000 n
0000000195 00000 n
trailer
<</Size 5/Root 1 0 R>>
startxref
248
%%EOF
+2 -3
View File
@@ -96,7 +96,7 @@ enum class OperatorType {
class Operator {
public:
static OperatorType operator_type_from_symbol(StringView symbol_string)
static Optional<OperatorType> operator_type_from_symbol(StringView symbol_string)
{
#define V(name, snake_name, symbol) \
if (symbol_string == #symbol) \
@@ -109,8 +109,7 @@ public:
if (symbol_string == "\"")
return OperatorType::TextNextLineShowStringSetSpacing;
dbgln("unsupported graphics symbol {}", symbol_string);
VERIFY_NOT_REACHED();
return {};
}
static char const* operator_name(OperatorType operator_type)
+4 -1
View File
@@ -596,7 +596,10 @@ PDFErrorOr<Vector<Operator>> Parser::parse_operators()
auto operator_string = StringView(m_reader.bytes().slice(operator_start, m_reader.offset() - operator_start));
m_reader.consume_whitespace();
auto operator_type = Operator::operator_type_from_symbol(operator_string);
auto maybe_operator_type = Operator::operator_type_from_symbol(operator_string);
if (!maybe_operator_type.has_value())
return error(ByteString::formatted("unsupported operator {}", operator_string));
auto operator_type = maybe_operator_type.release_value();
if (operator_type == OperatorType::InlineImageBegin) {
if (!operator_args.is_empty())