Skip to content

feat(receive): add maxsize argument to bound memory usage - #463

Open
Tieske wants to merge 1 commit into
masterfrom
feat/receive-limit
Open

feat(receive): add maxsize argument to bound memory usage#463
Tieske wants to merge 1 commit into
masterfrom
feat/receive-limit

Conversation

@Tieske

@Tieske Tieske commented Jul 30, 2026

Copy link
Copy Markdown
Member

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 third 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
Tieske force-pushed the feat/receive-limit branch 2 times, most recently from 138360b to 761a921 Compare July 30, 2026 18:22
@Tieske
Tieske requested a review from Copilot July 30, 2026 18:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 maxsize argument handling and early argument validation in buffer_meth_receive, plus a new internal BUF_OVERSIZED completion path.
  • Implement budget-aware recvline/recvall behavior 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
Tieske force-pushed the feat/receive-limit branch from 761a921 to 73b0780 Compare July 30, 2026 20:07
@Tieske
Tieske marked this pull request as ready for review July 30, 2026 20:29
@lunarmodules lunarmodules deleted a comment from Copilot AI Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants