Repository navigation
fix(protocols): rebuild the payload from info.to_dict() in from_data (#1447) - #1452
Conversation
|
Coverage: 89.51% (unit tier, Python 3.14,
Per-file detail: the |
|
Verdict: NEEDS CHANGES at Blocking: a UDP datagram carrying L2TPv2 (port 1701) still loses its payload in the dict rebuild.
The layers above (IPv4, Ethernet) then rebuild inexactly as well. Fix: match on Everything else holds:
Nit: Separate issue, not this PR: repeated IPv6 extension headers collide in the |
…o_dict omits __next_type__/__next_name__ (#1447) to_dict() leaves out the dispatch keys, so _make_payload fell back to NoPayload and a layer rebuilt from its dict lost everything past its own header. The dict is left as it is, since the dumps are written from it; the payload is found from its structure instead. - ProtocolBase._lookup_payload: the payload is the last key the data model does not declare whose value is a mapping, matched against the info_name of each protocol in __proto__ and its fallback. - IPv6._lookup_exthdr: recover the extension header chain by walking next from the keys the headers were written under. - HTTP.from_data: rebuild a dict into the HTTP/1.* or HTTP/2 data model by its keys, since the dispatcher's own model carries no version. - test_capture_roundtrip_runtime: drop the #1447 DICT_GAPS rows.
2a6d4fb to
c5c0024
Compare
|
Verdict: GOOD TO GO at
Nit: the Separately, unrelated to this PR: PCAPNG block layers need constructor keywords to rebuild, in both the dict and object form. That predates this PR, and the PR doesn't claim it. |
mypyon the 3 modules: no new errors vsmain;pylint: no new findings in the changed source;isortnot run with the repo configmake testpasses, and a test case covers the change — ordering legsfoundation528 OK,dumpkit227 OK,protocols/internet601 OK,protocols(rest) 1126 OK,project606 OK;test_capture_roundtrip_runtime.py4 passed, 20501 subtestsWhat is the purpose of your pull request?
fix— corrects a defectDescription of your pull request and other information
Closes #1447
to_dict()is left unchanged, because the dumps are written from it. Instead,_make_payloadfalls back to the dict's structure when__next_type__and__next_name__are absent. The payload is the last key the data model does not declare whose value is a mapping. It is matched against theinfo_nameof each protocol in__proto__and its fallback, not the class name, so L2TPv2'sl2tpresolves. IPv6 recovers__exthdr__by walkingnextover the extension-header keys. HTTP had a separate cause: its dispatcher's data model isRaw, soHTTP.from_datanow picks the HTTP/1.* data model if the dict hasreceipt, or HTTP/2 if it hassid.Over every sample capture, the dict-form rebuild is now byte-exact for Frame, Ethernet, ARP, IPv4, IPv6, TCP, UDP and HTTP. Ethernet goes from 22582 to 243047 of 243047 octets, and
ipv4.pcap#1 from 14 to 1870 of 1870. This PR drops the #1447 rows fromDICT_GAPSintest_capture_roundtrip_runtime.py, which leaves the table empty. Repeated IPv6 extension headers colliding into_dict()keys are #1453, which this PR does not fix.New
tests/protocols/test_to_dict_payload_roundtrip_1447_unit.pybuilds frames in memory, including UDP over L2TPv2. With the sources frommain, 54 cases fail across 5 of its 7 tests. The other 2 pin thatto_dictis unchanged and that a dict without a payload key yieldsNoPayload.