Skip to content

fix(internet): read a checksum behind a cut TSO IPv4 as truncated (#2689) - #2699

Merged
JarryShaw merged 1 commit into
mainfrom
fix/2689-tso-cut-checksum
Nov 2, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/2689-tso-cut-checksum

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • fix — corrects a defect

Description of your pull request and other information

Two cases where a checksum read INVALID, with a false ChecksumWarning, on a packet that was only cut by the capture:

  • Behind a TSO IPv4. An IPv4 Total Length of 0 reads as "the rest of the frame", so only the frame's lengths record a snaplen cut. Internet._decode_next_layer cleared frame_length regardless. It now takes declared: IPv4.read passes bool(ipv4.len), and AH in IPv4 mode passes False, so the cut reaches verify_message. verify_message adds the uncaptured octets for ICMP, IGMP and GRE alike. Every other Internet layer still clears frame_length.
  • A directly constructed GRE(cut). GRE.read reports TRUNCATED whenever its header carries the built-in __short_read__ record, so a cut anywhere in the header counts, not only one at or before the checksum.

Tests cut GRE, ICMP and IGMP at every point behind a TSO IPv4, with and without AH, and through PCAP and PCAP-NG. They also cut GRE headers at every octet. Each cut test fails on main. Whole packets, wrong checksums and declared lengths are the controls. Shipped captures parse identically to main.

Closes #2689

@JarryShaw JarryShaw added this to the PyPCAPKit v1.6 milestone Nov 2, 2026
@JarryShaw JarryShaw added bug Issues reporting a defect (set by the bug report template; a default, not an assessment) 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 9cc338739, from a Sonnet cross-review. Every cut behind a TSO IPv4 (ICMP, IGMPv2/v3 and GRE; with and without AH; over PCAP and PCAP-NG) reads TRUNCATED with no warning, 1920 cuts in all. Whole packets read VALID, and wrong checksums still warn. A cut GRE header reads TRUNCATED through the built-in record. Each mutation is caught, and captures are identical to the base.

Two small follow-ups go into this PR: IGMPv2(cut) built directly has the same defect GRE did, and pep.rst's bullet on GRE behind LinuxSLL is stale. I'll verify the amend. The from_data replay-order case is filed separately.

)

- IPv4 Total Length 0 (TSO): the payload runs to the end of the frame, but
  `Internet._decode_next_layer` cleared `frame_length` regardless, so GRE,
  ICMP and IGMP summed the captured octets of a snaplen-cut frame and read
  INVALID with a false `ChecksumWarning`. `_decode_next_layer` gains
  `declared`; `IPv4.read` passes false for a Total Length of 0 and AH always
  does, since its payload is the rest of its parent's. Every other Internet
  layer still clears it.
- `verify_message` now adds the frame's uncaptured octets itself, so ICMP and
  IGMP get the cut as GRE did; `GRE.read` drops its own copy of that term.
- `GRE(cut)` and `IGMPv1/v2/v3(cut)` on octets ending inside the message
  verified a zero-filled checksum and read INVALID; `GRE.read` and
  `IGMP._verify_checksum` read TRUNCATED whenever the header carries a
  `__short_read__` record.
- pep.rst: the GRE checksum bullet states the current truncation rule.

New tests in test_ipv4_tso_cut_checksum_2689_unit, test_gre_header_cut_2689_unit
and test_igmp_header_cut_2689_unit fail on main; sample captures parse
identically.
@JarryShaw
JarryShaw force-pushed the fix/2689-tso-cut-checksum branch from 9cc3387 to e5665a1 Compare November 2, 2026 22:41
@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed 9cc338739→e5665a11c, rebased onto 342fe7ebe with both follow-ups folded in. I checked the delta myself:

  • IGMP._verify_checksum reads TRUNCATED when the header carries __short_read__, which covers IGMPv1, IGMPv2 and IGMPv3. A new test cuts every IGMP header.
  • pep.rst's checksum bullet now states the current rule.

The three new modules fail on main and pass here, and captures are identical. This stays GOOD TO GO.

@JarryShaw
JarryShaw merged commit 7874807 into main Nov 2, 2026
11 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Nov 2, 2026
@JarryShaw
JarryShaw deleted the fix/2689-tso-cut-checksum branch November 2, 2026 22:44
@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
…s, the cut schema lists, the TSO checksum cut and short ZigBee keys into 1.6.0 (#2449)

- Breaking: MH (#2700) refuses a mobility option, or a sub-option, QoS
  attribute or CGA extension of one, whose fields do not take its length,
  where 1.5.x rebuilt another; QualityOfServiceOption gains a required
  tc_reserved. Prefix lengths are held to their field's width, the NAI and
  service identifier makers count octets, and a long-form DER CGA key
  parses. Folded into the MH/DSS and makers' range-check entries, with a
  QoS entry of its own; old and new values measured against v1.5.1.
- Fixed: ListField zero-fills a cut list of schema items, bounded by
  ZERO_PAD_BUDGET_RATIO with no free band, and a SACK past the data raises
  ProtocolError where it raised FieldValueError (#2701); a Decryption
  Secrets Block made from a short parsed ZigBee key is written as captured,
  and zigbee_key_held's schema holds the octets given (#2697).
- Folded into unreleased entries: radiotap's mixed bitmaps, their
  known-bits registries and BitmapField (#2696), into the Radiotap entry;
  the TSO and AH checksum cut (#2699), into the checksum and contextvars
  entries; the zero-filled SETTINGS and IGMPv3 records and the IGMPv3
  Additional Data rebuild (#2701), into the HTTP/2 SETTINGS and IGMP
  entries, dropping HTTPv2.make's unreleased frame_length.
- No entry for the docstring-and-test-only be83061 (#2695).
- 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

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(internet): a cut behind an IPv4 Total Length of 0 reads checksums INVALID

1 participant