Skip to content

corekit: a negative field length only warns in Schema.unpack, instead of raising ProtocolError #805

Description

@JarryShaw

Split off #799's review. httpv2.py:223's frame-length guard has been fixed
there so a buffer under nine octets, or a declared length exceeding the
buffer, is rejected uniformly before the schema layer runs. That closes the
outer-header truncation class, but not a related one one level deeper:
pkt['__length__'] in Schema.unpack (schema.py:894-899) is decremented by
each field's nominal width regardless of how many octets the buffer
actually had, and going negative is only ever a SchemaWarning — never a
raise. A field whose own length=lambda pkt: pkt['__length__']-style
callback resolves to that negative number builds a struct template like
'-5s', and struct.calcsize raises a bare struct.error for it: not a
ProtocolError, not a ValueError, uncatchable by ordinary caller code.

Reproduction, httpv2 specifically (buffer clears the fixed 9-octet header,
but the frame type's own fixed-width payload fields don't fit in what's
left):

import io
from pcapkit.protocols.application.httpv2 import HTTP as HTTPv2
data = b'\x00\x00\x15\x07\x00\x00\x00\x00\x00' + b'\xff' * 7  # GOAWAY, 16 octets
HTTPv2(io.BytesIO(data), 16)
# struct.error: bad char in struct format

Same shape at other sizes/types: GOAWAY at 9-16 octets (stream+error are
eight fixed octets alone), PUSH_PROMISE at 9-12, and any PADDED
DATA/HEADERS/PUSH_PROMISE whose pad_len exceeds what remains.

pkt['__length__'] is generic machinery, not an httpv2 particular — at
least these schema modules also key a field's length off it and would need
checking for the same latent crash before any fix lands:

  • pcapkit/protocols/schema/application/ftp.py
  • pcapkit/protocols/schema/application/httpv1.py
  • pcapkit/protocols/schema/application/httpv2.py
  • pcapkit/protocols/schema/application/ngap.py
  • pcapkit/protocols/schema/internet/hip.py
  • pcapkit/protocols/schema/internet/ipv6_route.py
  • pcapkit/protocols/schema/internet/mh.py
  • pcapkit/protocols/schema/link/ethernet.py
  • pcapkit/protocols/schema/misc/pcapng.py
  • pcapkit/protocols/schema/transport/sctp.py

Proposed fix: make a negative resolved field length raise ProtocolError
(or a dedicated subclass) in Schema.unpack and/or
FieldBase.length/Field.unpack, in place of the current
warn(f'packet length < 0: ...', SchemaWarning, ...). That closes the
inner-payload class the same way #799 closed the outer-header one, and lets
HTTP._guess_version's last arm in pcapkit/protocols/application/http.py
drop its struct.error suppression for good. Scoped as its own issue
because the change is in shared schema/field machinery, not a single
protocol, and needs the blast-radius check above before it lands.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingBreaks public-facing behaviour or API (apply alongside the type label)bugfixPull requests that fix a defect (fix: subject prefix)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions