nigig-org/crates/apps/pdf/pdf-cos/fuzz/fuzz_targets
andodeki 6a18886185
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
feat(pdf): Type 3 fonts and streaming interpretation — Phase 2 complete
The last two items of NIGIG_PDF_FEATURE_PARITY_PLAN.md Phase 2. Design and
merge criteria in REVIEWS/adr/0014-pdf-type3-fonts-and-streaming.md.

TYPE 3 FONTS DREW NOTHING

A Type 3 font's glyphs are not outlines - they are content streams, listed
in /CharProcs and mapped to text space by /FontMatrix. Probing a document
with one:

  fonts on page: ["T3"]
    T3: subtype=Type3 base=Unknown
  -> are the glyph procedures reachable? no CharProcs field exists
  -> is /FontMatrix exposed?             no field exists

The font was detected and then nothing could be done with it. /CharProcs and
/FontMatrix appeared nowhere in the crate, so the procedures were unreachable
and the text was silently invisible - a page that renders, reports no error,
and is missing content.

New pdf-document/src/type3.rs parses /FontMatrix, /CharProcs, /Differences,
/Widths, /FontBBox and the font's own /Resources, and resolves a character
code to its glyph procedure's decoded bytes. /FontMatrix is applied as
written rather than assumed to be the common 0.001 scale - Type 3 fonts
routinely use other matrices, which is the point of the entry. A missing
/CharProcs entry is a typed error naming the glyph, not a blank.

A THIRD BUG, FOUND WHILE WIRING d0/d1

The interpreter parsed both operators and discarded them:

  PdfOp::Type3Width(_wx, _wy) => {}
  PdfOp::Type3BBox(_x1, _y1, _x2, _y2) => {}

They are how a Type 3 glyph declares its advance, so even a renderer that
could draw the glyphs would stack them all at one point. Wiring them to the
device exposed that `d1` takes SIX operands - wx wy llx lly urx ury - and the
parser read four, so the "bounding box" was really the advance and the
advance was lost entirely. Now `Type3BBox { wx, wy, bbox }`, reading all six.

STREAMING INTERPRETATION

parse_content_stream materialised every operator into a Vec before
interpreting any of them: peak memory proportional to the whole content
stream, on a stream walked once and discarded. Adds ContentStreamIter and
interpret_streaming, with parse_content_stream reimplemented on top of the
iterator so there is ONE tokeniser rather than two that can drift.

Equivalence is proven, not asserted: a test compares both paths across every
corpus fixture, and a streaming_interpreter fuzz target compares them over
arbitrary bytes, which is where a divergence would actually hide.

4 corpus fixtures, 13 acceptance tests, 9 unit tests. Mutation-checked:
reverting d0 to a no-op fails glyph_advances_reach_the_device.

Phase 2 is now complete; the plan is updated with an item-by-item audit.
Several entries were already done (inline images, Do, text state, shading);
the plan's "biggest gap" was xref streams, closed in ADR 0013.

TEST_TARGET=pdf 615 -> 637, TEST_TARGET=pdf-ui 660 -> 682.
rustfmt and clippy -D warnings clean.
2026-08-16 17:28:44 +00:00
..
decode_stream.rs feat(pdf): complete Phase 6 testing infrastructure 2026-07-27 17:08:23 +00:00
decrypt.rs feat(pdf): implement encryption (Phase 8) 2026-07-28 17:39:38 +00:00
eval_function.rs feat(pdf): real colour spaces, ICC profiles and PDF functions 2026-07-28 20:48:55 +00:00
parse_colorspace.rs feat(pdf): real colour spaces, ICC profiles and PDF functions 2026-07-28 20:48:55 +00:00
parse_content_dict.rs feat(pdf): tagged structure tree, and the BMC bug that turned red green 2026-07-31 22:19:45 +00:00
parse_content_stream.rs feat(pdf): complete Phase 6 testing infrastructure 2026-07-27 17:08:23 +00:00
parse_document.rs feat(pdf): complete Phase 6 testing infrastructure 2026-07-27 17:08:23 +00:00
parse_ext_gstate.rs feat(pdf): transparency, and four operator-parsing bugs it exposed 2026-07-31 18:58:31 +00:00
parse_object.rs feat(pdf): complete Phase 6 testing infrastructure 2026-07-27 17:08:23 +00:00
parse_revision_chain.rs test(pdf): harden the xref revision chain 2026-07-28 16:58:16 +00:00
parse_signature.rs feat(pdf): read signatures, and fix a third ObjRef-destroying resolve 2026-07-31 20:02:29 +00:00
parse_xref.rs feat(pdf): complete Phase 6 testing infrastructure 2026-07-27 17:08:23 +00:00
parse_xref_stream.rs feat(pdf): read xref streams and object streams (PDF 1.5+) 2026-08-16 17:10:42 +00:00
streaming_interpreter.rs feat(pdf): Type 3 fonts and streaming interpretation — Phase 2 complete 2026-08-16 17:28:44 +00:00