Skip to content

Commit 712c6ad

Browse files
d4ddi0gitster
authored andcommitted
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 <[email protected]> Reviewed-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7e20105 commit 712c6ad

File tree

1 file changed

+7
-10
lines changed

1 file changed

+7
-10
lines changed

perl/Git.pm

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -890,20 +890,22 @@ sub cat_blob {
890890
my $size = $1;
891891

892892
my $blob;
893-
my $bytesRead = 0;
893+
my $bytesLeft = $size;
894894

895895
while (1) {
896-
my $bytesLeft = $size - $bytesRead;
897896
last unless $bytesLeft;
898897

899898
my $bytesToRead = $bytesLeft < 1024 ? $bytesLeft : 1024;
900-
my $read = read($in, $blob, $bytesToRead, $bytesRead);
899+
my $read = read($in, $blob, $bytesToRead);
901900
unless (defined($read)) {
902901
$self->_close_cat_blob();
903902
throw Error::Simple("in pipe went bad");
904903
}
905-
906-
$bytesRead += $read;
904+
unless (print $fh $blob) {
905+
$self->_close_cat_blob();
906+
throw Error::Simple("couldn't write to passed in filehandle");
907+
}
908+
$bytesLeft -= $read;
907909
}
908910

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

921-
unless (print $fh $blob) {
922-
$self->_close_cat_blob();
923-
throw Error::Simple("couldn't write to passed in filehandle");
924-
}
925-
926923
return $size;
927924
}
928925

0 commit comments

Comments
 (0)