Repository navigation
fix(reassembly): a TSO fragment's length is its captured length, and RCVBT covers the last block (#1555, #1565) - #1564
Conversation
|
Verdict: NEEDS CHANGES at Confirmed:
To fix: when TL is 0 and MF is set, a snaplen-cut fragment is taken at its cut length, but its last partial 8-octet block still gets marked as received. I reproduced it: a first fragment cut from 56 to 52 octets with TL 0 gives COMPLETE, 104 octets, with octets 52–55 zero-filled. With the real TL the same input is PARTIAL. The fix is to mark only whole 8-octet blocks when Also widen the code comment: a cut final fragment with TL 0 still comes out COMPLETE ( Separately: a fragment at the maximum offset (65,528) crashes reassembly on |
…RCVBT covers the last block (#1555, #1565) A TSO frame's IPv4 header carries Total Length 0, and since #1547 the adapters hand over the rest of the captured frame as its payload. The reassembler still took the data length from tl - ihl (-20), so every such datagram came out PARTIAL and empty, and a zeroed final fragment completed its datagram truncated. Separately, RCVBT had 8191 blocks for a 65535-octet buffer, so a fragment reaching octet 65528 raised IndexError. - ip.py: with tl 0, take the data length from the payload, as Wireshark does ("presumed TSO"); grow the buffer past 65535 octets (BIG TCP); leave a non-final TSO fragment's partial last block unmarked, since it can only be a snaplen cut. - ip.py: size RCVBT at 8192 blocks, and keep it in step on growth. - tests: the zeroed tcp.pcap under default, dpkt and scapy, fixed and stale checksums, reassembles as the unmodified capture; zeroed and cut fragments; a 70000-octet datagram; offset 65528 with 1 and 7 octets, MF set and clear, under IPv4 and IPv6. Reassembly output on every sample capture is unchanged.
16d81b9 to
e7c9e5f
Compare
|
Verdict: GOOD TO GO at
Residuals this PR doesn't introduce. I re-measured both and am filing them as follow-ups:
|
|
Coverage: 90.02% (unit tier, Python 3.14,
Per-file detail: the |
Please follow the guide below
You will be asked some questions, please read them carefully and answer honestly
Put an
xinto all the boxes [ ] relevant to your pull request (like that [x])Use Preview tab to see how your pull request will actually look like
Searched for similar pull requests
Followed the coding style (
make pylint,make mypy,make isort)make testpasses, and a test case covers the changeAdded a changelog entry under
docs/source/changelog/and regeneratedCHANGELOG.md, if the change is user-visible — N/A — centralised in docs(changelog): shared 1.5.0 changelog — long-lived, merges last (#610, #616, #617, #618, #620) #657What is the purpose of your pull request?
Tick the commit type your subject line carries.
fix— corrects a defectfeat— adds a featureperf— changes performance, not behaviourrefactor— changes neither behaviour nor performancetest— tests onlydocs— documentation onlyci— workflows or build toolingrelease— bumps the version or rolls up a distributionchore— anything elseDescription of your pull request and other information
Closes #1555. Closes #1565.
Both fixes are in
pcapkit/foundation/reassembly/ip.pyonly.#1555.
IP.reassemblytook a fragment's data length fromtl - ihl. A Total Length of 0 (TSO) gave-20: every TSO datagram came outPARTIALand empty, and a zeroed final fragment completed its datagram truncated. Withtl == 0, the data length is now the payload the adapter passed, which since #1547 is the rest of the captured frame. Wireshark 4.6.9 does the same before it reassembles ("presumed … TSO", then "[2 IPv4 Fragments (104 bytes)]", whichever fragment is zeroed).tcp.pcap(fixed and stale checksums) gives the unmodified capture's 4 ×COMPLETE(44/32/244/32) under default, dpkt, scapy and pypcapfile.RCVBTwith it.COMPLETE, becausePacketcarries no original length.tl = hdr_len + len(payload).#1565.
RCVBThad 8,191 blocks for a 65,535-octet buffer. A fragment reaching octet 65,528 made_detect_conflictsraiseIndexError. It now has 8,192 blocks. Tests cover offset 65,528 with 1 and 7 octets, MF set and clear, both strict modes, IPv4 and IPv6.Reassembly output on every sample capture is byte-identical to
main(all four engines, both strict modes).