Repository navigation
fix(reassembly): IP reassembly reports only the octets it holds (truncated fragments, strict runs, zero-length datagrams) - #1368
Conversation
|
Cross-review verdict on
Two body/docstring corrections, not blocking:
|
…cated fragments, strict runs, zero-length datagrams) - A fragment writes and marks only the octets the capture holds, clipped to its declared length and to the data buffer, which never changes length; a truncated fragment's partial last block stays a hole (#1357). - Strict runs stop at the total data length, and the last run is emitted even when it reaches the end of the bit table (#1358). - TDL is tested against -1 rather than for truthiness, so a zero-length datagram completes; completion is checked against the buffer's TDL on every fragment, not only the one with MF clear (#1359).
1273d32 to
f0dcf5d
Compare
|
Verdict re-pointed to |
|
Coverage: 88.98% (unit tier, Python 3.14,
Per-file detail: the |
Searched for similar pull requests
Followed the coding style (
make pylint,make mypy,make isort) — pylint (Makefile flags), mypy and isort run onreassembly/ip.py: cleanmake testpasses, and a test case covers the change — the modules listed below only, not the full suiteAdded a changelog entry — N/A, added centrally
fix— corrects a defectCloses #1357
Closes #1358
Closes #1359
One root cause:
IP.reassemblywrote and marked octets from the declared Total Length rather than the octets held, and tested TDL for truthiness. A fragment now writesmin(len(payload), TL-IHL)octets, clipped to the buffer, which never changes length. A truncated fragment leaves its partial last block clear. Strict runs stop at TDL and the last run is flushed. TDL is tested against-1, on every fragment.Behaviour change: a datagram now completes on whichever fragment fills the last hole. Before, it completed only on the fragment with MF clear, and otherwise waited for a flush.
COMPLETE, 300 zeros, tail shiftedPARTIAL; strict[1296, 400]; loose 2000 B,[0:1300]real (incl. 4 unmarked tail octets),[1300:1600]zero[1480, 48][1480, 43][8][8, 7]PARTIAL,()COMPLETE,b''Loose mode and truncated tails (documented, not changed). Receipt is tracked in 8-octet blocks, so a truncated fragment's partial last block is not marked. Strict runs leave it out. While TDL is unknown, loose mode returns the prefix up to the first clear bit, so it is left out there too. Once TDL is known, loose mode keeps its real octets and zero-fills only the rest of the hole. The
IPdocstring and thesubmitcomments now say this.Tests:
tests/foundation/reassembly/test_ip_reassembly_roundtrip_unit.pypasses 6, with 8 subtests. Withorigin/main'sip.pywritten over the fix, all 6 fail (11 failed counting subtests). These also pass:test_ip,test_ipv6,test_timeout,test_reassembly_base,tests/integration/test_reassembly_end_to_end.pyandtest_reassembly_engine_parity.py, which include theipv6.pcap4-fragment fixture under all 3 engines.tests/projectgives 382 passed, 8 skipped.util/run_unittest_leg.py foundationgives 489 tests, 2 failures and 11 errors, none in reassembly. The 2 failures aretest_runtime_enginesPCAPEngineTests, which fail identically onorigin/main'sip.py. The 11 errors come from #1372, a test onmainthat writes JSON without bound until the disk fills. Under a 200 MB file-size cap, the leg on this PR and on its base both give the same 2 failures and 2Errno 27errors.