Skip to content

Commit

Permalink
Git.pm: fix cat_blob crashes on large files
Browse files Browse the repository at this point in the history
Read and write each 1024 byte buffer, rather than trying to buffer
the entire content of the file.  We are only copying the contents to
a file descriptor and do not use it ourselves.

Previous code would crash on all files > 2 Gib, when the offset
variable became negative (perhaps below the level of perl),
resulting in a crash.  On a 32 bit system, or a system with low
memory it might crash before reaching 2 GiB due to memory
exhaustion.

This code may leave a partial file behind in case of failure, where
the old code would leave a completely empty file.  Neither version
verifies the correctness of the content.  Calling code must take
care of verification and cleanup.

Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Joshua Clayton authored and Junio C Hamano committed Feb 22, 2013
1 parent 7e20105 commit 712c6ad
Showing 1 changed file with 7 additions and 10 deletions.
17 changes: 7 additions & 10 deletions perl/Git.pm
Original file line number Diff line number Diff line change
Expand Up @@ -890,20 +890,22 @@ sub cat_blob {
my $size = $1;

my $blob;
my $bytesRead = 0;
my $bytesLeft = $size;

while (1) {
my $bytesLeft = $size - $bytesRead;
last unless $bytesLeft;

my $bytesToRead = $bytesLeft < 1024 ? $bytesLeft : 1024;
my $read = read($in, $blob, $bytesToRead, $bytesRead);
my $read = read($in, $blob, $bytesToRead);
unless (defined($read)) {
$self->_close_cat_blob();
throw Error::Simple("in pipe went bad");
}

$bytesRead += $read;
unless (print $fh $blob) {
$self->_close_cat_blob();
throw Error::Simple("couldn't write to passed in filehandle");
}
$bytesLeft -= $read;
}

# Skip past the trailing newline.
Expand All @@ -918,11 +920,6 @@ sub cat_blob {
throw Error::Simple("didn't find newline after blob");
}

unless (print $fh $blob) {
$self->_close_cat_blob();
throw Error::Simple("couldn't write to passed in filehandle");
}

return $size;
}

Expand Down

0 comments on commit 712c6ad

Please sign in to comment.