Skip to content

ipv6_opts' SMFIdentificationBasedDPDOption has a stray test field HOPOPT lacks, so identical octets fail there #441

Description

@JarryShaw

SMFIdentificationBasedDPDOption in pcapkit/protocols/schema/internet/ipv6_opts.py declares a test ForwardMatchField that its HOPOPT twin does not. The two modules are otherwise line-for-line equivalents, and this one extra field makes the same octets parse under HOPOPT and fail under IPv6-Opts.

The difference

Enumerating the class body from origin/main (c28ffc287):

hopopt.py     SMFIdentificationBasedDPDOption fields = ['info', 'tid', 'id']
ipv6_opts.py  SMFIdentificationBasedDPDOption fields = ['test', 'info', 'tid', 'id']
                                                        ^^^^^^ line 434
# pcapkit/protocols/schema/internet/ipv6_opts.py:434
    test: 'SMFDPDTestFlag' = ForwardMatchField(BitField(length=1, namespace={
        'mode': (0, 1),
    }))

Normalising both modules for their protocol names leaves ten differing lines: a module docstring, a five-line explanatory comment, and these three.

Why it is a stray rather than intentional

  • The enclosing _SMFDPDOption already declares a test ForwardMatchField (length=3), in both modules.
  • Nothing reads the nested one. smf_dpd_data_selector reads pkt['test']['mode'] and pkt['test']['len'], and that pkt is the enclosing schema's.
  • It is the only field in the class carrying no #: comment, unlike info, tid and id around it.

It predates #432, which neither added nor removed it.

Effect

ForwardMatchField consumes nothing from the stream but still occupies a slot in __buffer__, so it counts toward len(schema). The nested schema therefore over-reports its length by one octet, and OptionField accumulates that over-report against the declared option area until the area check fails.

Same wire layout, same octets, different outcomes — built through HOPOPT as 1100080100010100, option area 080100010100:

                 len(schema)
hopopt                 3        <- correct
ipv6_opts              4        <- one too many

HOPOPT(built, 8, extension=True)     -> options=[SMF_DPD, PadN]
IPv6_Opts(built, 8, extension=True)  -> ProtocolError: IPv6-Opts: invalid format

The error is raised at pcapkit/protocols/internet/ipv6_opts.py:497, the option-area threshold check in _read_ipv6_opts, reached from read at :315 via options=self._read_ipv6_opts(schema.len * 8 + 6) and unpack → __post_init__ at protocols/protocol.py:678.

Byte-for-byte identical on Python 3.10.20 and 3.14.7, so unlike the PCAP-NG failures in #439 this is not interpreter-dependent.

Provenance

Surfaced by the option round-trip harness in #440, which records ipv6-opts-option/SMF_DPD as a PARSE gap. Two corrections happened on the way to it and are worth recording, since both were wrong in ways that looked right:

Not fixed in #440 deliberately: that PR keeps git diff origin/main -- pcapkit/ empty, which is what makes a 258-case harness reviewable.

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

    bugIssues reporting a defect (set by the bug report template; a default, not an assessment)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions