]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pkt-line: eliminate the need for static buffer in packet_write_gently()
authorJeff Hostetler <jeffhost@microsoft.com>
Mon, 15 Mar 2021 21:08:18 +0000 (21:08 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 15 Mar 2021 21:32:50 +0000 (14:32 -0700)
Teach `packet_write_gently()` to write the pkt-line header and the actual
buffer in 2 separate calls to `write_in_full()` and avoid the need for a
static buffer, thread-safe scratch space, or an excessively large stack
buffer.

Change `write_packetized_from_fd()` to allocate a temporary buffer rather
than using a static buffer to avoid similar issues here.

These changes are intended to make it easier to use pkt-line routines in
a multi-threaded context with multiple concurrent writers writing to
different streams.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
pkt-line.c

index d633005ef746ad1eb7445cb75401e0c3f55a2312..66bd0ddfd1d023c944151fe1678fda21c9846550 100644 (file)
@@ -196,17 +196,26 @@ int packet_write_fmt_gently(int fd, const char *fmt, ...)
 
 static int packet_write_gently(const int fd_out, const char *buf, size_t size)
 {
-       static char packet_write_buffer[LARGE_PACKET_MAX];
+       char header[4];
        size_t packet_size;
 
-       if (size > sizeof(packet_write_buffer) - 4)
+       if (size > LARGE_PACKET_DATA_MAX)
                return error(_("packet write failed - data exceeds max packet size"));
 
        packet_trace(buf, size, 1);
        packet_size = size + 4;
-       set_packet_header(packet_write_buffer, packet_size);
-       memcpy(packet_write_buffer + 4, buf, size);
-       if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
+
+       set_packet_header(header, packet_size);
+
+       /*
+        * Write the header and the buffer in 2 parts so that we do
+        * not need to allocate a buffer or rely on a static buffer.
+        * This also avoids putting a large buffer on the stack which
+        * might have multi-threading issues.
+        */
+
+       if (write_in_full(fd_out, header, 4) < 0 ||
+           write_in_full(fd_out, buf, size) < 0)
                return error(_("packet write failed"));
        return 0;
 }
@@ -244,20 +253,23 @@ void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len)
 
 int write_packetized_from_fd(int fd_in, int fd_out)
 {
-       static char buf[LARGE_PACKET_DATA_MAX];
+       char *buf = xmalloc(LARGE_PACKET_DATA_MAX);
        int err = 0;
        ssize_t bytes_to_write;
 
        while (!err) {
-               bytes_to_write = xread(fd_in, buf, sizeof(buf));
-               if (bytes_to_write < 0)
+               bytes_to_write = xread(fd_in, buf, LARGE_PACKET_DATA_MAX);
+               if (bytes_to_write < 0) {
+                       free(buf);
                        return COPY_READ_ERROR;
+               }
                if (bytes_to_write == 0)
                        break;
                err = packet_write_gently(fd_out, buf, bytes_to_write);
        }
        if (!err)
                err = packet_flush_gently(fd_out);
+       free(buf);
        return err;
 }