Skip to content

feat: parser safety nets — multi-array validation + input-size cap - #3

Merged
ronaldtse merged 1 commit into
mainfrom
feat/parser-safety-nets
Jul 24, 2026
Merged

feat: parser safety nets — multi-array validation + input-size cap#3
ronaldtse merged 1 commit into
mainfrom
feat/parser-safety-nets

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

feat: parser safety nets — multi-array validation + input-size cap

The variable_array_sane? check introduced in PR #2 covered the
common single-array records (POLYGON, POLYLINE, POLYBEZIER, POLYDRAW,
etc.). This commit closes two remaining pathological-allocation
vectors.

What it does

Extends array sanity check to multi-array records.

  • POLYPOLYGON, POLYPOLYLINE, POLYPOLYGON16, POLYPOLYLINE16
    each carry TWO variable-length arrays: aPolyCounts
    (nPolys uint32s) and aptl/apts (cTotal entries). Previously
    only the second array was validated; corrupt first-array counts
    could still trigger massive allocations.
  • Both counts are now validated against nSize before bindata
    attempts to allocate.

Adds a global input-size cap.

  • MAX_INPUT_BYTES = 200 MB enforced at the parser entry point.
  • Anything larger raises Emf::FormatError immediately, before any
    allocation.

Why it matters

The original cpts=41026074 hang in PR #2 came from a single-array
record. The same class of bug exists for the multi-array records —
the parser is now safe against pathological inputs from any source
(corrupt fixtures, hostile callers, accidental wc -c outputs).

Verification

  • 321 examples, 0 failures.
  • Rubocop clean.
  • All 21 emf-corrupted/ files still parse without crashing or hanging.
  • Boundary check: a giant string of 200 MB zeros is rejected before
    parsing begins.

…input

The variable_array_sane? check (added in PR #2) covered POLYGON/POLYLINE/
POLYBEZIER/POLYBEZIERTO/POLYLINETO + their 16-bit variants + POLYDRAW/16.

This commit extends the check to multi-array records:
- POLYPOLYGON, POLYPOLYLINE, POLYPOLYGON16, POLYPOLYLINE16: each has TWO
  variable arrays (aPolyCounts and aptl/apts). Both counts are now
  validated against nSize before bindata tries to allocate.

Adds MAX_INPUT_BYTES = 200 MB guard at the parser entry point. Refuses
inputs larger than 200 MB before any allocation. The 5.7 MB EMF fixture
in the corpus is large; 200 MB is a generous safety margin.
@ronaldtse
ronaldtse merged commit bc7b973 into main Jul 24, 2026
@ronaldtse
ronaldtse deleted the feat/parser-safety-nets branch July 24, 2026 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant