summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Hescock <chescock@vistaprint.com>2016-01-11 17:09:32 -0500
committerChris Hescock <chescock@vistaprint.com>2016-01-12 10:08:58 -0500
commita7d9d93dad9b0965575906f5bf344867eb5b2a0e (patch)
tree8d615f290581916f8bd94b2a83aab7570d059353
parent700f0aff24d9b292f24d802c3af3b5c1705193c5 (diff)
downloadlibgit2-a7d9d93dad9b0965575906f5bf344867eb5b2a0e.tar.gz
Buffer sideband packet data
The inner packet may be split across multiple sideband packets.
-rw-r--r--src/transports/smart_protocol.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 1d46d4bc9..c8eb611d8 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -719,22 +719,20 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
return 0;
}
-static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
+static int add_push_report_sideband_pkt(git_push *push, git_buf *data_pkt_buf)
{
git_pkt *pkt;
- const char *line = data_pkt->data, *line_end;
- size_t line_len = data_pkt->len;
+ const char *line_end;
int error;
- while (line_len > 0) {
- error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
+ while (data_pkt_buf->size > 0) {
+ error = git_pkt_parse_line(&pkt, data_pkt_buf->ptr, &line_end, data_pkt_buf->size);
if (error < 0)
return error;
/* Advance in the buffer */
- line_len -= (line_end - line);
- line = line_end;
+ git_buf_consume(data_pkt_buf, line_end);
error = add_push_report_pkt(push, pkt);
@@ -753,6 +751,8 @@ static int parse_report(transport_smart *transport, git_push *push)
const char *line_end = NULL;
gitno_buffer *buf = &transport->buffer;
int error, recvd;
+ git_buf data_pkt_buf = GIT_BUF_INIT;
+ git_pkt_data *data_pkt;
for (;;) {
if (buf->offset > 0)
@@ -761,16 +761,21 @@ static int parse_report(transport_smart *transport, git_push *push)
else
error = GIT_EBUFS;
- if (error < 0 && error != GIT_EBUFS)
- return -1;
+ if (error < 0 && error != GIT_EBUFS) {
+ error = -1;
+ goto done;
+ }
if (error == GIT_EBUFS) {
- if ((recvd = gitno_recv(buf)) < 0)
- return recvd;
+ if ((recvd = gitno_recv(buf)) < 0) {
+ error = recvd;
+ goto done;
+ }
if (recvd == 0) {
giterr_set(GITERR_NET, "early EOF");
- return GIT_EEOF;
+ error = GIT_EEOF;
+ goto done;
}
continue;
}
@@ -781,8 +786,14 @@ static int parse_report(transport_smart *transport, git_push *push)
switch (pkt->type) {
case GIT_PKT_DATA:
- /* This is a sideband packet which contains other packets */
- error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt);
+ /* This is a sideband packet which contains other packets
+ * Buffer the data in case the inner packet is split
+ * across multiple sideband packets */
+ data_pkt = (git_pkt_data *)pkt;
+ git_buf_put(&data_pkt_buf, data_pkt->data, data_pkt->len);
+ error = add_push_report_sideband_pkt(push, &data_pkt_buf);
+ if (error == GIT_EBUFS)
+ error = 0;
break;
case GIT_PKT_ERR:
giterr_set(GITERR_NET, "report-status: Error reported: %s",
@@ -803,12 +814,24 @@ static int parse_report(transport_smart *transport, git_push *push)
git_pkt_free(pkt);
/* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
- if (error == GIT_ITEROVER)
- return 0;
+ if (error == GIT_ITEROVER) {
+ error = 0;
+ if (data_pkt_buf.size > 0) {
+ /* If there was data remaining in the pack data buffer,
+ * then the server sent a partial pkt-line */
+ giterr_set(GITERR_NET, "Incomplete pack data pkt-line");
+ error = GIT_ERROR;
+ }
+ goto done;
+ }
- if (error < 0)
- return error;
+ if (error < 0) {
+ goto done;
+ }
}
+done:
+ git_buf_free(&data_pkt_buf);
+ return error;
}
static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec)