Repository navigation
fix(schema): a header cut inside a fixed-width field rebuilds as captured (#1458, #1451) - #1465
Conversation
|
Coverage: 89.59% (unit tier, Python 3.14,
Per-file detail: the |
|
Verdict: NEEDS CHANGES at Blocking: the dict-form rebuild of a cut header still writes the field at full width. e = Ethernet(bytes(12) + b'\x08', 13)
len(Ethernet.from_data(e.info).data) # 13
len(Ethernet.from_data(e.info.to_dict()).data) # 14The reviewer saw this in 615 of 3894 cut runs. #1447/#1452 made the dict form a first-class round trip, so this needs fixing, with a test. The PR body's claim that "to_dict/from_dict carry the record" holds for Holds
Found outside this PR's scope, and filed:
|
e48586e to
857e497
Compare
…ured (#1458, #1451) When the data ended inside a field, Schema.unpack read the missing octets as zeros and recorded nothing, so from_data(info) wrote that field, and every field after it, at full width: Ethernet(bytes(12) + b'\x08') rebuilt as 14 octets, and a Routing header with 23 of 24 octets as 24. - Schema.unpack records the first field it reads short, and how many octets it got, as __short_read__; Schema.pack writes back only those, and Schema.to_dict/from_dict carry the record like __remainder__. - keep_short_read/replay_short_read carry the record through info: the Link, Internet, Transport and Application bases add it after a parse and cut a from_data rebuild back to it. It is an ordinary info key, so Info.to_dict carries it and from_data(info.to_dict()) replays it too; only a truncated header has it. - The #1454 edge tables drop the #1451/#1458 rows this closes, and the harness its two now-unused defect strings; five SCTP last-chunk pad rows remain, under #1474. Decoded values are unchanged: a truncated number still reads as zero-filled.
857e497 to
540c888
Compare
…tured (#1470) - PCAP Header calls #1465's keep_short_read/replay_short_read, so a header cut short rebuilds from its info as the octets captured, not all 24. - A PCAP-NG block the capture ends inside keeps its octets as truncated_raw; a rebuild parses them again instead of writing the block at its declared length (which wrote zeros, or raised ProtocolError). - A cut block whose own parser refuses the zero-filled fields is kept as an UnknownBlock rather than raising. - TLS and WireGuard key logs skip a last line the capture cut, and raise FieldValueError for any other malformed line (was a bare ValueError). Adds tests/protocols/misc/test_misc_short_read_1470_runtime.py.
|
Verdict: GOOD TO GO at
One point for the changelog: truncated headers now expose |
…tured (#1470) - PCAP Header calls #1465's keep_short_read/replay_short_read, so a header cut short rebuilds from its info as the octets captured, not all 24. - A PCAP-NG block the capture ends inside keeps its octets as __truncated_raw__; a rebuild parses them again instead of writing the block at its declared length (which wrote zeros, or raised ProtocolError). - A cut block whose own parser refuses the zero-filled fields is kept as an UnknownBlock rather than raising. - TLS and WireGuard key logs skip a last line the capture cut, and raise FieldValueError for any other malformed line (was a bare ValueError). Adds tests/protocols/misc/test_misc_short_read_1470_runtime.py.
…tured (#1470) - PCAP Header calls #1465's keep_short_read/replay_short_read, so a header cut short rebuilds from its info as the octets captured, not all 24. - A PCAP-NG block the capture ends inside keeps its octets as __truncated_raw__; a rebuild parses them again instead of writing the block at its declared length (which wrote zeros, or raised ProtocolError). - A cut block whose own parser refuses the zero-filled fields is kept as an UnknownBlock rather than raising. - TLS and WireGuard key logs skip a last line the capture cut, and raise FieldValueError for any other malformed line (was a bare ValueError). Adds tests/protocols/misc/test_misc_short_read_1470_runtime.py.
Searched for similar pull requests
Followed the coding style: mypy reports nothing on the new lines; pylint and isort not run
make testpasses, and a test case covers the change: everyrun_unittest_leg.pyleg (foundation 528, dumpkit 232, corekit 633, protocols/internet 617, protocols rest 1160, project 606, all OK) and the four edge modulesChangelog entry — N/A — centralised in docs(changelog): shared 1.5.0 changelog — long-lived, merges last (#610, #616, #617, #618, #620) #657
fix— corrects a defectCloses #1458
Closes #1451
When a capture ends inside a field,
Schema.unpacknow records that field and how many octets it read, as__short_read__.Schema.packwrites back only those octets.Schema.to_dictandSchema.from_dictcarry the record, as they already do__remainder__(#1380). TheLink,Internet,TransportandApplicationbases copy the record intoinfoafter a parse, andfrom_datacuts the rebuild back to it.The record is an ordinary
infokey, present only on a truncated header.Info.to_dicttherefore carries it, andfrom_data(info)andfrom_data(info.to_dict())both rebuild the capture exactly. Decoded values are unchanged, and no exceptions change, so there is no!.Dumps: all 69 dumps of the 23 captures (JSON, plist and tree) are byte-identical. A dump of a truncated header gains one entry under that layer,
__short_read__: tuple ('data', 19).Edge tables: the #1454 tables drop their #1451 and #1458 rows. Five SCTP rows for padding of the last chunk remain, now filed under #1474. The two harness defect strings they used are removed.
Sweep: the #1454 edge cases cut at every offset take 45,756 runs, and failures fall from 14,012 to 22. The 22 left are the SCTP last-chunk padding (#1455) and the HOPOPT extension-mode trim (#1446).
tests/protocols/test_short_read_roundtrip_unit.pyhas 8 tests and 1340 subtests. Onmainit fails 821. On this PR's previous head, itsto_dictassertions fail 812.