Describe the bug
When an IPv6 extension header fails to parse, @beholder substitutes a Raw — but IPv6's own chain-walk then reads .next off it, which Raw does not carry:
ipv6.py:329 info = next_.info # next_ is whatever _import_next_layer returned
ipv6.py:338 proto = info.next # AttributeError when next_ is the Raw fallback
The consequence is not confined to the extension header. The AttributeError escapes IPv6.read before IPv6's own info is returned, so the @beholder one level up turns the whole IPv6 packet into Raw — source, destination, hop limit and flow label lost along with the extension header.
Reproduction
Measured on main at 21b121c0e, and on PR #889's head, with PYTHONSAFEPATH=1 and pcapkit.__file__ asserted to the tree under test. A well-formed Mobility Header (an IPv6 extension header — Mobility_Header = 135 is in pcapkit/const/ipv6/extension_header.py:42) whose status byte is unassigned:
Ethernet/IPv6 assigned status -> payload=IPv6 protochain=Ethernet:IPv6:MH
Ethernet/IPv6 unassigned status -> payload=Raw protochain=Ethernet:Internet_Protocol_version_6
IPv6 alone unassigned status -> AttributeError: 'Raw' object has no attribute 'next'
Note both IPv6 and MH are absent from the degraded protochain.
It is not specific to that enum. On unmodified main, two unrelated MH failure modes raise the identical AttributeError: a truncated MH (6 bytes) and an absurd Header Len of 0xff. So any extension-header parse failure reaches it.
Expected behavior
A failed extension header degrades to Raw in place, leaving the IPv6 header's own parsed fields intact and the rest of the chain walked as far as it can be — which is what @beholder exists to provide. At minimum the walk should stop cleanly on a Raw rather than raising AttributeError, since Raw is a value _import_next_layer is documented to return.
System information
- Python 3.14.7, CPython, checkout at
21b121c0e.
Additional context
Surfaced while reviewing #889, which stops four mh.py helper enums from minting on an unassigned byte. #889 does not introduce this — it makes it far more reachable, turning a malformed-packet-only path into one a well-formed packet with an unrecognised status byte takes. It is out of scope there and #889 documents the real cost instead.
This also corrects a claim I made on #877 when recommending those enums raise: I said the cost was one MH message's parse. On the IPv6 path it is the whole IPv6 packet. See issues/877 for the correction.
Describe the bug
When an IPv6 extension header fails to parse,
@beholdersubstitutes aRaw— but IPv6's own chain-walk then reads.nextoff it, whichRawdoes not carry:The consequence is not confined to the extension header. The
AttributeErrorescapesIPv6.readbefore IPv6's own info is returned, so the@beholderone level up turns the whole IPv6 packet intoRaw— source, destination, hop limit and flow label lost along with the extension header.Reproduction
Measured on
mainat21b121c0e, and on PR #889's head, withPYTHONSAFEPATH=1andpcapkit.__file__asserted to the tree under test. A well-formed Mobility Header (an IPv6 extension header —Mobility_Header = 135is inpcapkit/const/ipv6/extension_header.py:42) whose status byte is unassigned:Note both
IPv6andMHare absent from the degraded protochain.It is not specific to that enum. On unmodified
main, two unrelated MH failure modes raise the identicalAttributeError: a truncated MH (6 bytes) and an absurdHeader Lenof0xff. So any extension-header parse failure reaches it.Expected behavior
A failed extension header degrades to
Rawin place, leaving the IPv6 header's own parsed fields intact and the rest of the chain walked as far as it can be — which is what@beholderexists to provide. At minimum the walk should stop cleanly on aRawrather than raisingAttributeError, sinceRawis a value_import_next_layeris documented to return.System information
21b121c0e.Additional context
Surfaced while reviewing #889, which stops four
mh.pyhelper enums from minting on an unassigned byte. #889 does not introduce this — it makes it far more reachable, turning a malformed-packet-only path into one a well-formed packet with an unrecognised status byte takes. It is out of scope there and #889 documents the real cost instead.This also corrects a claim I made on #877 when recommending those enums raise: I said the cost was one MH message's parse. On the IPv6 path it is the whole IPv6 packet. See
issues/877for the correction.