From e3862c9fb21c892afd5b41aa91ff8680a8ccb9dd Mon Sep 17 00:00:00 2001 From: Chris Hescock Date: Mon, 11 Jan 2016 17:09:32 -0500 Subject: [PATCH] Buffer sideband packet data The inner packet may be split across multiple sideband packets. --- src/transports/smart_protocol.c | 59 +++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 6363378ec..7d381b4cb 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -721,22 +721,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); @@ -755,6 +753,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) @@ -763,16 +763,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; } @@ -783,8 +788,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", @@ -805,12 +816,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)