feat(receive): add maxsize argument to bound memory usage - #463
Open
Tieske wants to merge 1 commit into
Open
Conversation
Tieske
force-pushed
the
feat/receive-limit
branch
2 times, most recently
from
July 30, 2026 18:22
138360b to
761a921
Compare
There was a problem hiding this comment.
Pull request overview
Adds an optional maxsize argument to client:receive() to cap how much data a single call may accumulate for *l and *a, preventing unbounded buffering when peers never send a newline or never close. This extends the existing receive API with a bounded-read mode and a new "oversized" error while preserving socket state and retry/drain invariants.
Changes:
- Add
maxsizeargument handling and early argument validation inbuffer_meth_receive, plus a new internalBUF_OVERSIZEDcompletion path. - Implement budget-aware
recvline/recvallbehavior to stop at the cap and surface"oversized"with an exact-cap partial. - Add tests covering boundary conditions and recovery idioms, and document the new argument/error semantics.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/utestclnt.lua | Adds unit tests for receive(..., maxsize) on key boundaries and error behavior. |
| test/testclnt.lua | Adds broader integration-style coverage for argument errors, *l/*a boundaries, drain idiom, and numeric-pattern behavior. |
| src/buffer.c | Implements maxsize validation, budgets for recvline/recvall, and maps cap hits to "oversized". |
| docs/tcp.html | Documents the new maxsize argument, the "oversized" error, and recommended drain/retry patterns. |
| CHANGELOG.md | Notes the new receive maxsize capability and "oversized" behavior in Unreleased. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
client:receive("*l") and receive("*a") are unbounded: a peer that never
sends a newline, or never closes, makes LuaSocket buffer until the
process runs out of memory (e.g. src/http.lua reading response headers
in a loop). Add an optional maxsize argument that caps the payload a
single call may accumulate, including prefix.
- Hoist all argument validation ahead of timeout_markstart() so bad
calls (maxsize < 1, #prefix >= maxsize, numeric pattern > maxsize)
raise before any I/O and leave the socket untouched.
- recvline/recvall take a budget and return a new internal
BUF_OVERSIZED code, surfaced to Lua as the "oversized" error
alongside "timeout"/"closed", with the partial held in the 3rd
return value.
- recvraw is left untouched: argument checks make the cap unreachable
for numeric patterns.
- Preserve three invariants: a timeout partial is always shorter than
maxsize (safe to retry as prefix), completion beats the cap for *a,
and no bytes are lost or skipped on overflow.
- tcp.c, unixstream.c and serial.c all share this code path unchanged.
Adds test coverage (argument errors, *l/*a boundaries, timeout/close
at the cap, the drain idiom, numeric patterns, unix-stream mirror) and
documents the new argument, error, and recovery idioms in docs/tcp.html.
Tieske
force-pushed
the
feat/receive-limit
branch
from
July 30, 2026 20:07
761a921 to
73b0780
Compare
Tieske
marked this pull request as ready for review
July 30, 2026 20:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
client:receive("*l")andreceive("*a")are unbounded: a peer that never sends a newline, or never closes, makes LuaSocket buffer until the process runs out of memory (e.g.src/http.luareading response headers in a loop). Add an optionalmaxsizeargument that caps the payload a single call may accumulate, including prefix.timeout_markstart()so bad calls (maxsize < 1,#prefix >= maxsize,numeric pattern > maxsize) raise before any I/O and leave the socket untouched.recvline/recvalltake a budget and return a new internalBUF_OVERSIZEDcode, surfaced to Lua as the "oversized" error alongside "timeout"/"closed", with the partial held in the third return value.recvrawis left untouched: argument checks make the cap unreachable for numeric patterns.maxsize(safe to retry asprefix), completion beats the cap for*a, and no bytes are lost or skipped on overflow.tcp.c,unixstream.candserial.call share this code path unchanged.Adds test coverage (argument errors,
*l/*aboundaries, timeout/close at the cap, the drain idiom, numeric patterns, unix-stream mirror) and documents the new argument, error, and recovery idioms indocs/tcp.html.