summaryrefslogtreecommitdiff
path: root/builtin/update-ref.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2018-10-30 23:23:12 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-10-31 04:05:26 (GMT)
commitccdc4819d56202d49e35fbfec2960e221576f862 (patch)
treec2635c135675e39a6920b279d88d53ad69fadfc9 /builtin/update-ref.c
parent5632baf238c09b2556c92897bcf0d1fc236499ba (diff)
downloadgit-ccdc4819d56202d49e35fbfec2960e221576f862.zip
git-ccdc4819d56202d49e35fbfec2960e221576f862.tar.gz
git-ccdc4819d56202d49e35fbfec2960e221576f862.tar.bz2
check_stream_sha1(): handle input underflow
This commit fixes an infinite loop when fscking large truncated loose objects. The check_stream_sha1() function takes an mmap'd loose object buffer and streams 4k of output at a time, checking its sha1. The loop quits when we've output enough bytes (we know the size from the object header), or when zlib tells us anything except Z_OK or Z_BUF_ERROR. The latter is expected because zlib may run out of room in our 4k buffer, and that is how it tells us to process the output and loop again. But Z_BUF_ERROR also covers another case: one in which zlib cannot make forward progress because it needs more _input_. This should never happen in this loop, because though we're streaming the output, we have the entire deflated input available in the mmap'd buffer. But since we don't check this case, we'll just loop infinitely if we do see a truncated object, thinking that zlib is asking for more output space. It's tempting to fix this by checking stream->avail_in as part of the loop condition (and quitting if all of our bytes have been consumed). But that assumes that once zlib has consumed the input, there is nothing left to do. That's not necessarily the case: it may have read our input into its internal state, but still have bytes to output. Instead, let's continue on Z_BUF_ERROR only when we see the case we're expecting: the previous round filled our output buffer completely. If it didn't (and we still saw Z_BUF_ERROR), we know something is wrong and should break out of the loop. The bug comes from commit f6371f9210 (sha1_file: add read_loose_object() function, 2017-01-13), which reimplemented some of the existing loose object functions. So it's worth checking if this bug was inherited from any of those. The answers seems to be no. The two obvious candidates are both OK: 1. unpack_sha1_rest(); this doesn't need to loop on Z_BUF_ERROR at all, since it allocates the expected output buffer in advance (which we can't do since we're explicitly streaming here) 2. check_object_signature(); the streaming path relies on the istream interface, which uses read_istream_loose() for this case. That function uses a similar "is our output buffer full" check with Z_BUF_ERROR (which is where I stole it from for this patch!) Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/update-ref.c')
0 files changed, 0 insertions, 0 deletions