Skip to content

Validate list and element counts; skip empty header lines - #89

Closed
gaoflow wants to merge 1 commit into
dranjan:masterfrom
gaoflow:fix-negative-counts-and-blank-lines
Closed

Validate list and element counts; skip empty header lines#89
gaoflow wants to merge 1 commit into
dranjan:masterfrom
gaoflow:fix-negative-counts-and-blank-lines

Conversation

@gaoflow

@gaoflow gaoflow commented Jul 31, 2026

Copy link
Copy Markdown

Three validation defects in the hand-rolled parser, all from counts never checked as non-negative:

  1. A negative binary list count was accepted. _read_array computed a negative size, so BytesIO read the whole rest of the file as the list (silent corruption) and real files raised a misleading "early end-of-file"; with int8 values and count -1 it silently swallowed the file on both stream types. Repro: PlyData.read(BytesIO(b"ply\nformat binary_little_endian 1.0\nelement f0 1\nproperty list int8 int8 v0\nend_header\n" + b"\xff\x01\x02\x03")) returns a 3-element list from count -1. Now rejected as negative array length -1.
  2. element vertex -1 leaked a raw numpy ValueError instead of the documented PlyParseError.
  3. Empty header lines (skip documented in 1.1.3) were rejected as "early end-of-file" by a stale EOF check in consume().

The count check lives in the shared _read_array helper, which also fixes the ASCII list path (was "malformed input"). One existing test asserted the old buggy line number for (b"ply\n\n"); updated 2 -> 3. Suite: 130 passed (was 120).


📚 Documentation preview 📚: https://python-plyfile--89.org.readthedocs.build/en/89/

A negative binary list count was never rejected: _read_array computed a
negative size and stream.read() read the entire remaining file (BytesIO)
or raised a misleading 'early end-of-file' (files). The same class of
bug let a negative ASCII list count fall through as 'malformed input'
and a negative element count leak a raw numpy ValueError.

Check counts for non-negativity at the shared _read_array helper and at
parse_element/_from_fields, carrying the real message through
PlyElementParseError. The blank-line skip promised since 1.1.3 is now
reachable: the stale pre-rewrite EOF sentinel in consume() fired on
empty lines first and misreported them as 'early end-of-file'.
@dranjan

dranjan commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Hey @gaoflow, thanks for the interest. Yeah, I guess there's insufficient validation for item counts in general. IMO it's very unlikely to encounter this in practice, so it's not super urgent to patch this, but we do try to be pretty strict about validation, so we should do it anyway.

In general this project doesn't accept AI-authored contributions, so I'll probably have to close this PR, but I do appreciate learning about the deficiency, even if it's minor.

@dranjan dranjan closed this Jul 31, 2026
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.

2 participants