Expand description
#1667: a framing pump in front of tower-lsp’s transport.
tower-lsp 0.20 reads stdin through a FramedRead, and a framed stream
ends at its first decode error. So one message whose body isn’t valid JSON
stopped the whole server, with exit 0 and nothing on stderr. The trigger
is reachable from a well-behaved client: JSON.stringify writes a lone
UTF-16 surrogate in a string as \udcff, which serde_json rejects.
pump reads the client’s frames itself and forwards to the server only
bodies that parse, so a bad one can’t end the stream:
- a body that parses is forwarded unchanged;
- a body whose only fault is a lone surrogate escape is repaired (each
lone
\uD800–\uDFFFbecomes\uFFFD) and forwarded. U+FFFD is one UTF-16 code unit, like the surrogate it replaces, so the client’s positions into the text stay aligned with the server’s; - any other body is logged and skipped. Its
idcan’t be recovered from unparseable JSON, so no error response is possible.
A header block without Content-Length, or a stream that ends mid-frame
(a truncated body), leaves nothing to resynchronise on: the pump stops,
with the reason logged, and the server sees end of input.
Enums§
Constants§
- MAX_
BODY - #1771 review: the largest body
pumpaccepts. AContent-Lengthis otherwise trusted and allocated in full before the body arrives, so one corrupted digit could abort the process. A frame over this is unrecoverable framing, like a missingContent-Length. 128 MiB is far above any real message (adidOpencarries one file’s text). - MAX_
HEADER_ LINE - The longest header line
pumpreads, so a client that never sends a newline can’t grow the line without limit.