You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(protocols): a payload layer parsed from a short stream rebuilds default-filled octets #1170
Describe the bug
A payload layer parsed from a stream shorter than its own header is default-filled, so from_data rebuilds octets that were never captured. #1169 fixes only the zero-octet IPv4 case behind #1167.
To Reproduce
IPv6: a 40-octet header declaring a 168-octet UDP payload parses as IPv6:UDP:Raw and rebuilds to 48 octets. I re-ran this on main1b0862e72. A header cut at 30 octets also gains UDP:Raw.
IPv4 with a partial UDP header: header plus 1 octet rebuilds to 28 octets against 21 captured; plus 4 octets, 28 against 24.
IPv4 header cut short:test.pcapng frame 3 has 18 captured octets but rebuilds to 20. The missing low half of dst is zero-filled, and nothing records the captured length.
Expected behavior
A layer parsed from too few octets should rebuild to what was captured, not to a default-filled header.
Additional context _import_next_layer in internet.py, protocol.py and transport.py picks NoPayload only when length == 0. A short-stream guard is needed there and in UDP and the other next layers. Found by the #1169 cross-review. The fix touches the same files as #1169, so this waits on it.
Decision needed on #1171 (fixes #1170): what should a frame cut inside the IP header become?
#1171 adds one shared guard. When fewer octets are captured than the next layer's header needs, the payload becomes Raw instead of a header padded out with zeros. That fixes the IPv6 and partial-UDP cases exactly. It also changes test.pcapng frame 3, which carries 18 of 20 IPv4 header octets:
(2) Keep IPv4 parsed for a header cut short, as on main today. Frame 3 then rebuilds to 20 octets, because the zero-filled low half of dst comes back, until a captured-length field is added to the schema. That would be a public schema addition.
My recommendation is (1): it is the only option that rebuilds exactly what was captured, with no new public field. It does drop fields from truncated headers, though, so it is your call.
That makes (1) a public-contract change for snaplen-truncated captures, so I have labelled #1171breaking. A third option worth weighing:
(3) Keep the typed layer and flag it as truncated, so the real fields survive and the rebuild writes only the captured octets. That needs a new truncation flag, the same kind of public addition as (2).
The code itself was reviewed GOOD TO GO: both ordering legs pass on the merged tree, and the 1612-frame sweep changes only frame 3.
Recorded: the maintainer merged #1171 at 03:24Z, which settles this as option (1). A frame cut inside a header now yields Raw and rebuilds exactly what was captured, and the typed fields of a truncated header are no longer exposed. The #1171 cross-review's remaining gaps (IPv6_Route/MH understated hints, ApplicationBase not routed through the guard) will be filed separately.
Activity
JarryShaw commentedon Oct 7, 2026
Blocked until #1169 merges, because the fix touches
ipv4.pyand the shared_import_next_layerpath that #1169 also changes.JarryShaw commentedon Oct 7, 2026
Unblocked: #1169 merged at 02:25Z. A worker is on it now.
JarryShaw commentedon Oct 7, 2026
Decision needed on #1171 (fixes #1170): what should a frame cut inside the IP header become?
#1171 adds one shared guard. When fewer octets are captured than the next layer's header needs, the payload becomes
Rawinstead of a header padded out with zeros. That fixes the IPv6 and partial-UDP cases exactly. It also changestest.pcapngframe 3, which carries 18 of 20 IPv4 header octets:Raw, so the 32 captured octets rebuild exactly. The parsed IPv4 fields (src,ttl, the declared length 300, …) are no longer available as anIPv4layer. Two merged tests (fix(protocols): from_data keeps declared lengths on truncated captures #1166, fix(protocols): a capture cut inside the IPv4 header rebuilds with a fabricated UDP header #1169) are updated to expect this.maintoday. Frame 3 then rebuilds to 20 octets, because the zero-filled low half ofdstcomes back, until a captured-length field is added to the schema. That would be a public schema addition.My recommendation is (1): it is the only option that rebuilds exactly what was captured, with no new public field. It does drop fields from truncated headers, though, so it is your call.
JarryShaw commentedon Oct 7, 2026
Addendum to the decision above, from the #1171 cross-review. Option (1) drops real leading fields, not only fabricated trailing ones:
mainexposessrc,protocol,ttl,idandchecksum, all real, plus a zero-filleddst. fix(protocols): a payload layer parsed from a short stream rebuilds default-filled octets #1171 givesRaw, so.info.srcraisesAttributeError.maingivesUDPwith the real ports 53/53. fix(protocols): a payload layer parsed from a short stream rebuilds default-filled octets #1171 givesRaw, so the ports are gone.That makes (1) a public-contract change for snaplen-truncated captures, so I have labelled #1171
breaking. A third option worth weighing:The code itself was reviewed GOOD TO GO: both ordering legs pass on the merged tree, and the 1612-frame sweep changes only frame 3.
JarryShaw commentedon Oct 7, 2026
Recorded: the maintainer merged #1171 at 03:24Z, which settles this as option (1). A frame cut inside a header now yields
Rawand rebuilds exactly what was captured, and the typed fields of a truncated header are no longer exposed. The #1171 cross-review's remaining gaps (IPv6_Route/MHunderstated hints,ApplicationBasenot routed through the guard) will be filed separately.fix(protocols): drop the warnings of a next layer replaced by Raw (#1580