ref:b18689e7d5623f5e91387a7e467f03bb60f74565

fix: buffer partial data in UploadPack v1 to prevent split-data loss

UploadPack v1 had the same class of bug we fixed in v2: when SSH splits protocol data mid-pkt-line, parse_want_lines and parse_have_lines silently dropped the incomplete data and either prematurely ended negotiation (wants phase) or lost have SHAs (haves phase). Fix: propagate {:need_more, data} from the parsers back to feed/2 so it buffers full_data in negotiate_buffer for the next call — matching the pattern ReceivePack already uses correctly. Also adds 6 new split-data tests: - UploadPack v1: 4 tests (2-part, 3-part, boundary, haves-split) - ReceivePack: 2 tests (pack-phase split, mid-pkt-line command split) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SHA: b18689e7d5623f5e91387a7e467f03bb60f74565
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-03-14 02:27
Parents: 1bd54cd
3 files changed +250 -2
Type
lib/ex_git_objectstore/protocol/upload_pack.ex +12 −2
@@ -84,6 +84,10 @@
{:ok, wants, haves, :continue} ->
handle_negotiation_continue(%{state | negotiate_buffer: <<>>}, wants, haves)
{:need_more, _} ->
# Not enough data yet — buffer and wait for more
{<<>>, %{state | negotiate_buffer: full_data}}
{:error, _reason} ->
nak = PktLine.encode("NAK")
{nak, %{state | phase: :done, negotiate_buffer: <<>>}}
@@ -230,11 +234,17 @@
{:ok, haves, :continue} ->
{:ok, wants, haves, :continue}
{:need_more, _} ->
{:need_more, data}
{:error, _} = err ->
err
end
{:need_more, _} ->
{:need_more, data}
{:error, _} = err ->
err
end
@@ -262,7 +272,7 @@
parse_want_lines(rest, acc)
{:need_more, _} ->
{:need_more, data}
{:ok, Enum.reverse(acc), <<>>}
{:error, _} = err ->
err
@@ -295,7 +305,7 @@
parse_have_lines(rest, acc)
{:need_more, _} ->
{:need_more, data}
{:ok, Enum.reverse(acc), :continue}
{:error, _} = err ->
err