summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sha1_file.c3
-rwxr-xr-xt/t1450-fsck.sh19
2 files changed, 21 insertions, 1 deletions
diff --git a/sha1_file.c b/sha1_file.c
index d77b915db6..7d016184a3 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -3847,7 +3847,8 @@ static int check_stream_sha1(git_zstream *stream,
* see the comment in unpack_sha1_rest for details.
*/
while (total_read <= size &&
- (status == Z_OK || status == Z_BUF_ERROR)) {
+ (status == Z_OK ||
+ (status == Z_BUF_ERROR && !stream->avail_out))) {
stream->next_out = buf;
stream->avail_out = sizeof(buf);
if (size - total_read < stream->avail_out)
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 770d68e44e..1f245bbc5f 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -646,6 +646,25 @@ test_expect_success 'fsck detects trailing loose garbage (large blob)' '
test_i18ngrep "garbage.*$blob" out
'
+test_expect_success 'fsck detects truncated loose object' '
+ # make it big enough that we know we will truncate in the data
+ # portion, not the header
+ test-genrandom truncate 4096 >file &&
+ blob=$(git hash-object -w file) &&
+ file=$(sha1_file $blob) &&
+ test_when_finished "remove_object $blob" &&
+ test_copy_bytes 1024 <"$file" >tmp &&
+ rm "$file" &&
+ mv -f tmp "$file" &&
+
+ # check both regular and streaming code paths
+ test_must_fail git fsck 2>out &&
+ test_i18ngrep corrupt.*$blob out &&
+
+ test_must_fail git -c core.bigfilethreshold=128 fsck 2>out &&
+ test_i18ngrep corrupt.*$blob out
+'
+
# for each of type, we have one version which is referenced by another object
# (and so while unreachable, not dangling), and another variant which really is
# dangling.