Git.pm: fix cat_blob crashes on large files
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>
This commit is contained in:

committed by
Junio C Hamano

parent
7e2010537e
commit
712c6adaee
17
perl/Git.pm
17
perl/Git.pm
@ -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.
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user