Summary
The git-remote-gitlawb helper bridges git's stateful upload-pack connect stream onto a single stateless HTTP POST, so it deadlocks on an incremental (multi-round) fetch. read_upload_pack_request treats a flush pkt (0000) as "keep reading" and only breaks on the done\n pkt-line, and handle_connect issues exactly one POST after done. In an incremental fetch git sends wants, then a have-batch terminated by a flush, and blocks waiting for the server's ACK/NAK before sending done. The helper is blocked reading stdin for a done that never comes; git is blocked reading the helper's stdout for a response that is never sent. The fetch hangs until the request timeout.
A fresh clone (the client sends wants + done in one shot) works, which is why this was not caught earlier.
Where
crates/gitlawb-node/../git-remote-gitlawb/src/main.rs — read_upload_pack_request (breaks only on done\n or EOF; continues past a flush) and the single-POST flow in handle_connect.
Reproduced by execution
Live repro against a local node: built a ~50-commit shared history, cloned via gitlawb://, advanced the server by a few commits, then git fetch origin.
- Fresh clone (control): exit 0, ~1s.
- Incremental fetch, few haves (git short-circuits, sends
want + haves + done in one shot): exit 0, ~0s.
- Incremental fetch, >32 haves (forces multi-round): hung the full 40s, killed by
timeout (exit 124).
GIT_TRACE_PACKET confirmed git sent 1 want, 32 have lines, a flush 0000, and zero done, then blocked. Only the initial ref advertisement ever came back.
Impact
Any fetch where the client has more than ~32 commits of overlapping history with the server (the common "pull updates into an existing clone") hangs indefinitely. Not a security issue; a functional break in the helper's fetch path.
Options
- Implement git's stateless-RPC multi-round negotiation (a POST per have-batch, streaming ACK/NAK back), or
- advertise/implement the
stateless-connect capability instead of connect.
Pre-existing; surfaced while verifying the receive-pack advertisement fix end to end.
Summary
The
git-remote-gitlawbhelper bridges git's stateful upload-packconnectstream onto a single stateless HTTP POST, so it deadlocks on an incremental (multi-round) fetch.read_upload_pack_requesttreats a flush pkt (0000) as "keep reading" and only breaks on thedone\npkt-line, andhandle_connectissues exactly one POST afterdone. In an incremental fetch git sendswants, then ahave-batch terminated by a flush, and blocks waiting for the server's ACK/NAK before sendingdone. The helper is blocked reading stdin for adonethat never comes; git is blocked reading the helper's stdout for a response that is never sent. The fetch hangs until the request timeout.A fresh clone (the client sends
wants +donein one shot) works, which is why this was not caught earlier.Where
crates/gitlawb-node/../git-remote-gitlawb/src/main.rs—read_upload_pack_request(breaks only ondone\nor EOF;continues past a flush) and the single-POST flow inhandle_connect.Reproduced by execution
Live repro against a local node: built a ~50-commit shared history, cloned via
gitlawb://, advanced the server by a few commits, thengit fetch origin.want+ haves +donein one shot): exit 0, ~0s.timeout(exit 124).GIT_TRACE_PACKETconfirmed git sent 1want, 32havelines, a flush0000, and zerodone, then blocked. Only the initial ref advertisement ever came back.Impact
Any fetch where the client has more than ~32 commits of overlapping history with the server (the common "pull updates into an existing clone") hangs indefinitely. Not a security issue; a functional break in the helper's fetch path.
Options
stateless-connectcapability instead ofconnect.Pre-existing; surfaced while verifying the receive-pack advertisement fix end to end.