Skip to content

inet6: parse only complete Routing Header addresses - #5142

Open
KernelClint wants to merge 2 commits into
secdev:masterfrom
KernelClint:inet6-routing-header-complete-addresses
Open

inet6: parse only complete Routing Header addresses#5142
KernelClint wants to merge 2 commits into
secdev:masterfrom
KernelClint:inet6-routing-header-complete-addresses

Conversation

@KernelClint

Copy link
Copy Markdown
Contributor

An IPv6 Routing Header carries a list of addresses, and its len field counts the header's size in
eight-byte units. The generic form parses that list at
scapy/layers/inet6.py:997-1007:

length_from=lambda pkt: 8 * pkt.len

Addresses are sixteen bytes, so an odd len describes a whole number of eight-byte units but only
half an address. The field at scapy/layers/inet6.py:252-271 converts each chunk it is given into
an address, including a final incomplete one, and parsing raises partway through. The packet ends
as IPv6 followed by unparsed data, and anything reading the layer chain — a bridge_and_sniff()
transform, for instance — does not see the transport header that a conforming receiver does.

The change parses only the complete entries and keeps an odd trailing eight bytes as generic
routing data:

-                                length_from=lambda pkt: 8 * pkt.len)]
+                                length_from=lambda pkt: 16 * (pkt.len // 2)),
+                   ConditionalField(
+                       StrLenField("data", b"", length_from=lambda pkt: 8),
+                       lambda pkt: (bool(pkt.getfieldval("data"))
+                                    if pkt.len is None else pkt.len % 2),
+                   )]

The extra field is conditional on an odd length, so even-length Routing Headers keep exactly the
representation and build output they have today. The length adjustment is updated to match so a
header built with trailing data round-trips.

The added regression parses an odd-length header and asserts it yields an empty address list, the
trailing data, and the transport header beneath it. With only the test, the IPv6 suite reports 522
passed and 1 failed; with the source change, 523 passed and 0 failed.

Performance was measured on one computer, before and after the fix: parsing a valid even-length
header took 6,777.1 ns before and 6,574.2 ns after. Repeat runs of this test moved by about 8%,
which is wide enough that only a large change would show — this is not one.

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.64%. Comparing base (b3bbcc8) to head (013d9ec).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #5142   +/-   ##
=======================================
  Coverage   80.63%   80.64%           
=======================================
  Files         390      390           
  Lines       96936    96936           
=======================================
+ Hits        78168    78176    +8     
+ Misses      18768    18760    -8     
Files with missing lines Coverage Δ
scapy/layers/inet6.py 88.71% <ø> (ø)

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

AI-Assisted: yes (GPT-5.6-Cyber)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant