git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git hang with corrupted .pack

From
Junio C Hamano <gitster@pobox.com>
Date
Oct 20, 2009, 16:52 UTC
Message-ID
<7viqeaovmp.fsf@alter.siamese.dyndns.org>
In-Reply-To
<20091014142351.GI9261@spearce.org>
"Shawn O. Pearce" <spearce@spearce.org> writes:
Show 10 quoted lines
> Z_BUF_ERROR is returned from inflate() if either the input buffer
> needs more input bytes, or the output buffer has run out of space.
> Previously we only considered the former case, as it meant we needed
> to move the stream's input buffer to the next window in the pack.
>
> We now abort the loop if inflate() returns Z_BUF_ERROR without
> consuming the entire input buffer it was given, or has filled
> the entire output buffer but has not yet returned Z_STREAM_END.
> Either state is a clear indicator that this loop is not working
> as expected, and should not continue.

When the inflated contents is of size 0, avail_out would be 0 and avail_in would still have something because the input stream needs to have the end of stream marker that is more than zero byte long.

If that is more than one-byte long, and your avail_in originally fed only the first byte from that sequence, what happens? Wouldn't inflate eat all what was given (now avail_in is zero), updated its internal state but it still hasn't produced anything (avail_out is zero)?

I am not saying the end-of-stream is more than one-byte long (I didn't check), but we had a similar bug arising from confusing "no more output data" and "fully consumed input stream" (e.g. 456cdf6 (Fix loose object uncompression check., 2007-03-19).

Something like that may be what is happening to cause problem Alex is seeing.

I think the corrupt packdata detection needs an output buffer at least one-byte larger than what is needed to store the correct result. Then when we get BUF_ERROR:

 - We never look at avail to see if it is zero; !avail_out is not the same
   as "it stopped because it ran out of output space".  It might mean
   "there is nothing more to come but the input stream ended before
   signalling that fact to the inflate engine fully".
 - We do look at avail_out to find how much data we ended up getting.  If
   inflate has consumed more buffer than we planned to give it, the stream
   is corrupt (at least it is not what we expected to see);
Show 20 quoted lines
>  		st = git_inflate(&stream, Z_FINISH);
> +		if (st == Z_BUF_ERROR && (stream.avail_in || !stream.avail_out))
> +			break;
>  		curpos += stream.next_in - in;
>  	} while ((st == Z_OK || st == Z_BUF_ERROR) &&
>  		 stream.total_out < sizeof(delta_head));
> @@ -1594,6 +1596,8 @@ static void *unpack_compressed_entry(struct packed_git *p,
>  		in = use_pack(p, w_curs, curpos, &stream.avail_in);
>  		stream.next_in = in;
>  		st = git_inflate(&stream, Z_FINISH);
> +		if (st == Z_BUF_ERROR && (stream.avail_in || !stream.avail_out))
> +			break;
>  		curpos += stream.next_in - in;
>  	} while (st == Z_OK || st == Z_BUF_ERROR);
>  	git_inflate_end(&stream);
> -- 
> 1.6.5.52.g0ff2e
>
> -- 
> Shawn.
Previous: Pascal ObryNext: Junio C Hamano
Message 18 of 23 in “git hang with corrupted .pack”
  1. Andy IsaacsonOct 14, 2009
  2. Shawn O. PearceOct 14, 2009
  3. Nicolas PitreOct 14, 2009
  4. Shawn O. PearceOct 14, 2009
  5. Nicolas PitreOct 14, 2009
  6. Shawn O. PearceOct 14, 2009
  7. Nicolas PitreOct 14, 2009
  8. Junio C HamanoOct 15, 2009
  9. Alex RiesenOct 20, 2009
  10. Sverre RabbelierOct 20, 2009
  11. Alex RiesenOct 20, 2009
  12. Junio C HamanoOct 26, 2009
  13. Alex RiesenOct 26, 2009
  14. Shawn O. PearceOct 26, 2009
  15. Pascal ObryNov 3, 2009
  16. Shawn O. PearceNov 3, 2009
  17. Pascal ObryNov 3, 2009
  18. Junio C HamanoOct 20, 2009
  19. Junio C HamanoOct 20, 2009
  20. Junio C HamanoOct 20, 2009
  21. Nicolas PitreOct 20, 2009
  22. Junio C HamanoOct 20, 2009
  23. Junio C HamanoOct 22, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.