Skip to content

fix(fields): #811 misreports a malformed template as a negative length, and never prevents the negative length #825

Description

@JarryShaw

Two related defects in #811's negative-length guard, both surfaced by #823's cross-review and both confirmed here.

1. The message is a category error. FieldBase.length (pcapkit/corekit/fields/field.py:284-290) catches struct.error blanket and unconditionally reports f'Field {self.name} resolved to a negative length; template={self.template!r}'. But struct.calcsize raises the same error for a malformed template as for a negative count — measured on 3.14.7:

calcsize('-1s') -> struct.error: bad char in struct format
calcsize('Xs')  -> struct.error: bad char in struct format

So a schema with a typo'd template is reported as a negative length, which sends the reader to the wrong cause. The guard should distinguish the two — the negative case is detectable from the resolved length before calcsize is called at all.

2. The negative length is reported, never prevented. A SchemaWarning: packet length < 0: -1 fires before the ProtocolError, so pkt['__length__'] still goes negative and the schema still builds a '-1s' template; #811 converts the resulting exception rather than stopping the arithmetic. #823's reviewer found 32 inputs across two different fields (debug and fragment) taking this path in a 1210-case sweep, so it is a class of input, not one packet. The real fix bounds pkt['__length__'] at the schema layer.

Related and worth re-measuring in the same change: http.py:318-319 (except (ValueError, struct.error) in the preface arm) took zero hits across that 1210-case sweep and may now be unreachable, and http.py:416's contextlib.suppress(ProtocolError, struct.error) is likely in the same position. Neither is safe to simply delete — StructError subclasses struct.error, and the comment at :401-402 explains why removing a suppression from a non-final arm previously caused an HTTP/1→HTTP/2 mislabel.

Note the test pinned by #823 asserts the current message verbatim, so fixing (1) will red it; assertIn('negative length', …) there would survive.

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

    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