mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-06 02:21:45 +00:00
- Huffman leaf tables where one code begins another are malformed; the shorter leaf would end the longer code early and misalign the payload. - A model-file end past the input is malformed rather than clipped. - Each schema entry costs one element, so empty programs are not free. - tessellations() carries the globals schema's remaining allowance into the tessellation reader: one stream, one budget. - A face behaviour wider than 16 bits is malformed, not zeroed. - Coordinate arrays that are not whole points are malformed; a partial last normal drops the stored normals, as an unusable normal slot does. - Triangles a TESS_3D's faces emit are charged to the element budget as they are made, since faces may reuse one index range. - TriangleMesh::transformed drops stored normals under a projective matrix (last row not [0, 0, 0, w]). - Placement::tessellation's doc says placements() does not check it against the tessellation section. Each fix has a test, seen failing with the fix reverted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
pdfcraft-prc
A reader for PRC (ISO 14739-1), the 3D model format a PDF /3D stream of /Subtype /PRC carries (ISO 32000-2 §13.6.3).
- Layer: L0, standalone. No dependency on any other PdfCraft crate.
- Licence: MIT OR Apache-2.0. Inflation through
flate2with the pure-Rustminiz_oxidebackend. #![forbid(unsafe_code)]. Never panics on input: inflated bytes, decoded elements, schema steps and walk depth are capped, and damage returnsPrcError.
API
PrcFile::parse(data) -> Result<PrcFile, PrcError> // header, file structures, model file
PrcFile::parse_with_limit(data, max_inflated) -> Result<PrcFile, PrcError>
FileStructure::section(SectionKind) -> &[u8] // inflated globals / tree / tessellation / geometry / extra geometry
FileStructure::schema() -> Result<Schema, PrcError> // the globals section's leading schema
FileStructure::tessellations() -> Result<Vec<Tessellation>, PrcError> // meshes, wires, markups, compressed meshes
PrcFile::placements() / placements_with(StyleAlpha, EntityOverrides) -> Result<Vec<Placement>, PrcError>
PrcFile::model_tree() -> Result<Vec<ModelNode>, PrcError> // the assembly tree as a model-tree panel lists it
Placement::triangle_colours(&TriangleMesh) -> Option<Vec<Option<Rgba>>>
TriangleMesh::transformed(&Matrix) -> TriangleMesh
Schema::read(&mut BitReader) / Schema::skip_added_fields(entity_type, &mut BitReader)
BitReader: bit, bits, character, unsigned_integer, integer, integer_vbn, double_vbn, nbits_then_unsigned, string, float_as_bytes, double
MAX_INFLATED_BYTES(512 MiB) bounds every section together;TooLargereports the limit hit.MAX_DECODED_ELEMENTS(2^24) bounds the array elements one pass decodes (a tree walk, or onetessellationscall), since a single bit can decode to a 4-8 byte element;TooManyElementsreports it.- Schema programs (how a newer producer describes fields it added) run under a nesting ceiling (64) and
MAX_SCHEMA_STEPS(2^22), shared likeMAX_DECODED_ELEMENTSby every program one pass runs. Unsupportednames constructs the reader cannot step over (schema pointer fields,Value_CurveIs3D).Tessellation::Meshis aTriangleMesh: positions, triangles, one triangle range per face, the stored normals and texture coordinates with each triangle's corner indices into them, and per-triangle line-attribute styles.Wireis polylines;Markupis read past.Tessellation::Compressedis read to its end so later entities decode; its triangles are not rebuilt yet.- A face may carry at most 8 texture-coordinate sets; more is
Malformed. Optimised vertex colours areUnsupported. - The product tree: each drawable tessellation placed by its occurrence path's locations and the item's coordinate
systems (a 4x4
Matrix), coloured by the style inheritance rules, with occurrences' entity references applied (EntityOverrides: subtree, everywhere or ignored) and style transparency combined with material alpha byStyleAlpha. A prototype's part is coloured by its own file structure's styles. EachModelNodelists its name, where the name came from, its visibility and the range of placements it drew. - Occurrence and prototype cycles are
Malformed; the walk is capped at depth 64, 2^20 visits andMAX_PLACEMENTS. - A tree's markups (PMI), views, scene lights and clipping planes are read past, not modelled; so are textures.
- Not yet in the crate: rebuilding compressed meshes, textures.
- The
Doublecode table's rows come from prc-rs (MIT); its notice is insrc/acof/table.rs. A few reading choices also follow prc-rs; each is marked// prc-rs:in the source.