Skip to content

feat(link): decode radiotap TLV items a producer cut short (#2655) - #2690

Merged
JarryShaw merged 1 commit into
mainfrom
feat/2655-radiotap-short-tlv
Nov 2, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
feat/2655-radiotap-short-tlv

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • feat — adds a feature

Description of your pull request and other information

radiotap.org's TLV page says a producer may omit an item's trailing zero octets. A TLV item shorter than its layout was kept raw. It now decodes as its layout padded with those zeros. For example, a U-SIG TLV of 8 of its 12 octets now decodes.

The cut is Schema's built-in short-read record. _read_tlv_data unpacks the item at its layout's full length, so Schema.unpack zero-fills it and records the cut. _make_tlv_data hands that record back, so Schema.pack writes the octets as captured through make(). from_data replays the captured fields, as before. When the zero-pad limits refuse the padding, the item stays raw and nothing is logged. Items longer than a fixed layout stay raw.

Following the same rule, a cut EHT user word and a vendor TLV cut inside its header decode too.

U-SIG, S1G, EHT and vendor items cut at a field boundary and inside a field are each compared with the whole item. Every test fails on main. Whole items, #2576's library vectors and every sample capture are unchanged from main.

Closes #2655

@JarryShaw JarryShaw added this to the PyPCAPKit v1.6 milestone Nov 2, 2026
@JarryShaw JarryShaw added feat Pull requests that add a new capability (feat: subject prefix) review: running A cross-review is in flight against the current head - no verdict yet labels Nov 2, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Nov 2, 2026
@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Nov 2, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO at 437e17a76, from a Sonnet cross-review.

  • The built-in does the work. _pack_tlv_data only hands the schema's own __short_read__ back to it, and Schema.pack makes the cut.
  • Every short item rebuilds exactly. All 31 TLV-capable types, cut at every length, decode as the zero-padded item, and make() writes back the captured octets.
  • Refusals are quiet. At the zero-pad limits, refused items stay raw, keep their octets and log nothing.
  • The two calls beyond the issue are justified. radiotap.org's TLV page has parsers accept partial data, with omitted trailing octets taken as zero. That covers the cut EHT user word and the cut vendor header.
  • Nothing else changed. Against main, only items shorter than their layout differ.

The review found two test gaps, which the worker is adding: EHT cuts at 1 and 3 octets into a user word, and a list-form record. I corrected the body: only make() re-encodes TLVs.

radiotap.org lets a producer leave off the octets it does not fill at the end
of a TLV item, and a parser reads them as zeros. Such an item stayed raw.

- _read_tlv_data unpacks data short of its schema, or of the vendor header, at
  the schema's full length, rounded up to a whole list item, so Schema.unpack
  zero-fills it and records the cut; the decoded data keeps it as
  __short_read__. Data past a fixed layout stays raw.
- _make_tlv_data packs through _pack_tlv_data, which hands the record back to
  the schema, so Schema.pack writes the octets as captured. A malformed
  record, or vendor data after a cut header, raises ProtocolError.
- Both unpacks share the CaughtByCaller(FieldValueError) guard, so a cut the
  zero-pad limits refuse stays raw, quietly.
- The module docstring, radiotap.rst, the TLV data model and make()'s Raises
  describe it.
- Tests: U-SIG, S1G, EHT and vendor items cut at a field boundary and inside
  a field, each against its zero-padded control; from_data and make() round
  trips; quietness; the padding-limit refusal; a registered layout. The #2576
  pins on a short S1G and a ragged EHT now expect them decoded.
@JarryShaw
JarryShaw force-pushed the feat/2655-radiotap-short-tlv branch from 437e17a to c3fc0d3 Compare November 2, 2026 21:33
@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed 437e17a76→c3fc0d3d5, a test-only amend that adds the two cases the review asked for. EHT cuts at 41 and 43 octets kill the rounding-sign mutant, and a list-form record kills the tuple-only mutant. pcapkit/ is unchanged, so the verdict stays GOOD TO GO.

@JarryShaw
JarryShaw merged commit 342fe7e into main Nov 2, 2026
59 checks passed
@JarryShaw
JarryShaw deleted the feat/2655-radiotap-short-tlv branch November 2, 2026 21:59
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Nov 2, 2026
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Nov 2, 2026
JarryShaw added a commit that referenced this pull request Nov 2, 2026
…h refusals and the Windows leg's argument file into 1.6.0 (#2449)

- Breaking: MH(raw) and TCP(raw) (#2683) raise ProtocolError for an MH
  message whose Header Len is short of its fields, or a DSS option of a
  length its flags do not give, where 1.5.x read the gap as zeros and
  rebuilt it longer; a cut MH keeps its declared Header Len. The entry gives
  the old and new results, measured against v1.5.1.
- Folded into unreleased entries: radiotap's decoded optional fields,
  Radiotap.__field__ with register_field and register_radiotap_field, the
  RadiotapField schemas and pcapkit.const.radiotap with its crawlers (#2657),
  and cut TLV items decoding zero-padded (#2690), into the Radiotap entry,
  with the IEEE 802.11 entry's Flags clause corrected; #2657's ruling on code
  to layout tables, into the conventions entry; the Windows leg's argument
  file (#2681), into the CI legs entry, as the cycle's other CI changes have
  entries.
- No entry for the test-only 42a6133.
- CHANGELOG.md regenerated; util/changelog_md.py --check passes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat Pull requests that add a new capability (feat: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

feat(link): decode radiotap TLV items a producer cut short

1 participant