Skip to content

http: return one Content-Length message per packet - #5134

Open
KernelClint wants to merge 1 commit into
secdev:masterfrom
KernelClint:http-one-message-per-packet
Open

http: return one Content-Length message per packet#5134
KernelClint wants to merge 1 commit into
secdev:masterfrom
KernelClint:http-one-message-per-packet

Conversation

@KernelClint

Copy link
Copy Markdown
Contributor

Scapy's HTTP stream session accumulates bytes until a message is complete, then returns it. For a
message with Content-Length, completeness is decided at
scapy/layers/http.py:665-745
by comparing the buffer length against the header length plus the declared body length.

The test is correct, but the packet returned is built from the whole accumulated buffer. If one
socket read carried two complete requests, the extra bytes ride along inside the first packet.
ForwardMachine then calls its policy callback once and forwards the serialisation of everything it
was given, so the second request crosses without ever being offered to the callback.

The change records where the message actually ends and represents the remainder as padding:

-                    detect_end = lambda dat: len(dat) - http_length >= length
+                    metadata["http_end"] = http_end = http_length + length
+                    detect_end = lambda dat: len(dat) >= http_end
...
             if detect_end(data):
+                http_end = metadata.get("http_end")
+                if http_end is not None and len(data) > http_end:
+                    return cls(data[:http_end]) / conf.padding_layer(data[http_end:])
                 return http_packet

The stream session already carries padding forward to the next message, so the second request is
returned on the following iteration and gets its own callback. No ForwardMachine-specific parsing
is added.

The added regression feeds two complete requests in one read and asserts the callback sees both.
Without the source change it fails.

Performance was measured on one computer, before and after the fix: a forwarded request took
32.5 µs before and 32.0 µs after. Repeat runs of this test moved by about 7%, which is wide enough
that only a large change would show — this is not one.

AI-Assisted: yes (GPT-5.6-Cyber)
@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.63%. Comparing base (b3bbcc8) to head (b9c9677).

Files with missing lines Patch % Lines
scapy/layers/http.py 87.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5134      +/-   ##
==========================================
- Coverage   80.63%   80.63%   -0.01%     
==========================================
  Files         390      390              
  Lines       96936    96943       +7     
==========================================
+ Hits        78168    78172       +4     
- Misses      18768    18771       +3     
Files with missing lines Coverage Δ
scapy/layers/http.py 83.41% <87.50%> (+0.02%) ⬆️

... and 6 files with indirect coverage changes

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

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