Skip to content

SettingsFrame.settings passes a Schema class to ListField's item_type instead of a SchemaField #459

Description

@JarryShaw

SettingsFrame.settings passes a Schema class where ListField expects a field instance, with the resulting type error silenced by a # type: ignore[arg-type].

The site

pcapkit/protocols/schema/application/httpv2.py:283-285:

#: Settings.
settings: 'list[SettingPair]' = ListField(
    length=lambda pkt: pkt['__length__'],
    item_type=SettingPair,  # type: ignore[arg-type]
)

Every other ListField in the tree wraps its schema item in a SchemaField — for example pcapkit/protocols/schema/transport/tcp.py:393 is item_type=SchemaField(length=8, schema=SACKBlock), and internet/hip.py:260, internet/mh.py:535 and transport/sctp.py:702 follow the same shape.

Confirmed on e2d8ed6d1

SettingPair is a SchemaMeta -> Schema subclass: True
ListField._item_type is: SchemaMeta

So _item_type holds the metaclass-produced class object rather than a field, and the type: ignore is what let it through review — mypy had it right.

Consequence

ListField.unpack's schema branch calls self._item_type(packet) to build a configured per-item field (see #433, which corrected a related bug on that line). Calling a Schema class with a packet dict does not produce a field; it attempts to construct a schema instance from a dict positionally. Depending on the branch taken, this either raises or silently mis-parses.

Why this was unreachable until now

It sits behind the nested-packet fault in #445: the SETTINGS frame's pack path died earlier with KeyError: 'length'. PR #457 fixes #445, and this becomes reachable — the agent implementing it reported SETTINGS as one of five HTTP/2 frames that then fail on distinct, previously-unreachable defects.

Fix

Wrap it as the siblings do:

item_type=SchemaField(schema=SettingPair),

and remove the # type: ignore[arg-type], confirming with mypy rather than assuming — the baseline is 128 errors in 41 files. A regression test should exercise a real SETTINGS frame round trip rather than a fake, since a fake with a compatible __call__ would hide the distinction.

Provenance

Surfaced by the agent implementing #445 (PR #457) and verified independently before filing. Related: #433 (the same ListField schema branch), and #445 which currently masks this.

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