git/0001-packfile-Correct-zlib-buffer-handling.patch
Todd Zullinger 20fad240e8 packfile: Correct zlib buffer handling on aarch64 (#1582555)
A recent zlib build with optimization for ARM exposed an issue in git's
packfile handling.

Thanks to Pavel Cahyna for the initial report and debugging and Jeremy
Linton for further diagnosis and the subsequent patch.

The patch is currently being discussed upstream¹.  Until it is accepted,
apply it only on aarch64 to avoid any unexpected issues with other
arches.

¹ https://public-inbox.org/git/20180525231713.23047-1-lintonrjeremy@gmail.com/T/#u
2018-05-29 14:28:31 -04:00

51 lines
2.0 KiB
Diff

From 0255347aed203301302e3f8e39fa87349e178019 Mon Sep 17 00:00:00 2001
From: Jeremy Linton <lintonrjeremy@gmail.com>
Date: Fri, 25 May 2018 17:56:01 -0500
Subject: [PATCH] packfile: Correct zlib buffer handling
The buffer being passed to zlib includes a null terminator that
git needs to keep in place. unpack_compressed_entry() attempts to
detect the case that the source buffer hasn't been fully consumed
by checking to see if the destination buffer has been over consumed.
This yields two problems, first a single byte overrun won't be detected
properly because the Z_STREAM_END will then be set, but the null
terminator will have been overwritten. The other problem is that
more recent zlib patches have been poisoning the unconsumed portions
of the buffers which also overwrites the null, while correctly
returning length and status.
Lets rely on the fact that the source buffer will only be fully
consumed when the when the destination buffer is inflated to the
correct size. We can do this by passing zlib the correct buffer size
and properly checking the return status. The latter check actually
already exists if the buffer size is correct.
Signed-off-by: Jeremy Linton <lintonrjeremy@gmail.com>
---
packfile.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packfile.c b/packfile.c
index 7c1a2519fc..245eb32041 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1416,7 +1416,7 @@ static void *unpack_compressed_entry(struct packed_git *p,
return NULL;
memset(&stream, 0, sizeof(stream));
stream.next_out = buffer;
- stream.avail_out = size + 1;
+ stream.avail_out = size;
git_inflate_init(&stream);
do {
@@ -1424,7 +1424,7 @@ static void *unpack_compressed_entry(struct packed_git *p,
stream.next_in = in;
st = git_inflate(&stream, Z_FINISH);
if (!stream.avail_out)
- break; /* the payload is larger than it should be */
+ break; /* done, st indicates if source fully consumed */
curpos += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR);
git_inflate_end(&stream);