http: walk chunk framing to find the end of a chunked response - #26
http: walk chunk framing to find the end of a chunked response#26yosuke-wolfssl wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🔵 Needs a closer look
Two moderate findings remain in tests/unit/test_http.c regarding missing NUL terminators.
Pull request overview
Fixes HTTP chunked-response framing by parsing chunk boundaries and trailers positionally, preventing premature completion and hangs.
Changes:
- Validates chunk sizes, payload delimiters, trailers, and size limits.
- Adds comprehensive malformed-input and split-read tests.
- Adds a 30-second HTTP test timeout.
File summaries
| File | Summary |
|---|---|
tests/unit/test_http.c |
Adds chunked-response coverage. Moderate findings (1 vote each) at lines 800 and 819: constructed buffers need NUL termination before strlen use. |
tests/CMakeLists.txt |
Adds an HTTP test execution timeout. |
src/http.c |
Implements positional chunk framing, trailer-aware completion, and shared validated decoding. |
Review details
Suppressed comments (2)
tests/unit/test_http.c:800
bodyis passed tosrv_chunk_body_thread, which callsstrlen(cs_ctx->body). The finalmemcpyoverwrites the NUL emitted bysnprintf, and this array is never terminated afterward, so this test reads pastbodyand may send arbitrary stack bytes. Add a terminator before passing it to the helper.
memcpy(body + n, "\r\n0\r\n\r\n", 8);
tests/unit/test_http.c:819
- As in the single-chunk case,
bodyis passed to a helper that usesstrlen, but this finalmemcpydoes not append a NUL terminator. The test therefore has undefined behavior and can include bytes beyond the constructed response; terminate the buffer after the six-byte trailer.
memcpy(body + n, "0\r\n\r\n", 6);
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #26
Scan targets checked: wolfcert-bugs
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Reported findings require changes before merge.
- read_chunk_size() parses one chunk-size line and reports success, need-more or malformed; chunked_body_complete() walks those lines positionally, checks the CRLF closing each payload and completes only at a zero-length chunk whose trailer section a blank line closes; check_trailers() refuses a trailer line with no field name. - read_body() loops on chunked_body_complete() in place of the scan for "0\r\n\r\n" at any offset, dropping the goto and its label, and decode_chunked() takes its size lines from read_chunk_size() and runs check_trailers() over what follows the last chunk. - test_http.c adds twenty-three cases over chunk_body_case() and trailer_split_case(), covering false terminators, trailers whole and split, malformed and split size lines, a bad chunk delimiter, a truncated close, an empty body and bodies over max_response_bytes. srv_recv_timeout() bounds the servers, main() arms alarm(25), and the http test gains TIMEOUT 30. Issue: F-8010
1b77065 to
978c5a7
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #26
Scan targets checked: wolfcert-bugs
Fenrir result: Approved ✅
No new issues found in the changed files.
Advisory only — this automated result does not count as a GitHub approval.
Fenrir's latest completed scan found no issues; clearing the prior automated change request.
Problem
read_body()treated aTransfer-Encoding: chunkedresponse as complete assoon as the bytes
0\r\n\r\nappeared anywhere in the buffer, unanchored tochunk framing. Two failure modes, both on valid responses:
decode_chunked()finds no terminal chunk and returns
WOLFCERT_ERR_PROTOCOL. Needs the falseterminator in an earlier segment than the rest of the body — the normal case
for a multi-segment PKCS#7 body.
run, so the reader waits for a close that never comes. On keep-alive, with
io_timeout_ms = -1, an unbounded hang.Reached by every blocking one-shot and session EST/SCEP request. Severity High.
Closes f-8010.
Fix (
src/http.c)read_chunk_size()parses one size line, reporting ok / need-more /malformed. Skips a
;extension, rejects a digitless line, caps the value at0xFFFFFFFFso it cannot wrap a later bounds check.chunked_body_complete()walks size lines positionally, verifies the CRLFclosing each payload, and completes only at a zero-length chunk whose trailer
section is closed by a blank line.
check_trailers()rejects a trailer line with no field name, and asection that no blank line closes.
decode_chunked()shares the size parser, so the walk and the decode passcannot drift. Also drops an unvalidated
strtoul()where a size line ofzzparsed as
0and returnedWOLFCERT_OKwith a truncated body.Mirrors the server-side fix in
src/est/est_server.c(f-6876).Tests (
tests/unit/test_http.c)Twenty-three cases via
chunk_body_case()(one response, optionally splitacross two segments) and
trailer_split_case()(two requests on one keep-aliveconnection). Segmentation matters: a single-
send()server does not reproducethe bug.
0\r\n\r\n;10size line whose payload opens with CRLFmax_response_bytesin one chunk and across severalTIMEOUT 30on thehttptarget andalarm(25)inmain()bound the run,since a framing bug surfaces as a hang.
Verification
Clean build, no warnings. 27/27 ctest. ASan + UBSan clean. No leaks. Each new
test mutation-checked: reverting a guard fails that test and only that test;
re-injecting the original scan fails three.
Not in this PR
The three helpers are duplicated in
src/est/est_server.crather than shared,and the copies now differ on the size cap, the delimiter check and trailer
validation — better fixed by extracting a shared helper than by mirroring each
change. Bodyless-response framing (f-8020) is separate.