diff options
author | Jeff King <peff@peff.net> | 2016-06-30 05:09:16 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-07-01 10:25:46 -0700 |
commit | d1657b570a44108e49032962da201aad48689605 (patch) | |
tree | 8c1b5d49c51b24e2dc64cc4d2a01227e1354d139 /t/t5000-tar-tree.sh | |
parent | e51217e15c3eb89d18b313dad32db1787d4f2a44 (diff) | |
download | git-d1657b570a44108e49032962da201aad48689605.tar.gz git-d1657b570a44108e49032962da201aad48689605.tar.xz |
archive-tar: write extended headers for file sizes >= 8GB
The ustar format has a fixed-length field for the size of
each file entry which is supposed to contain up to 11 bytes
of octal-formatted data plus a NUL or space terminator.
These means that the largest size we can represent is
077777777777, or 1 byte short of 8GB. The correct solution
for a larger file, according to POSIX.1-2001, is to add an
extended pax header, similar to how we handle long
filenames. This patch does that, and writes zero for the
size field in the ustar header (the last bit is not
mentioned by POSIX, but it matches how GNU tar behaves with
--format=pax).
This should be a strict improvement over the current
behavior, which is to die in xsnprintf with a "BUG".
However, there's some interesting history here.
Prior to f2f0267 (archive-tar: use xsnprintf for trivial
formatting, 2015-09-24), we silently overflowed the "size"
field. The extra bytes ended up in the "mtime" field of the
header, which was then immediately written itself,
overwriting our extra bytes. What that means depends on how
many bytes we wrote.
If the size was 64GB or greater, then we actually overflowed
digits into the mtime field, meaning our value was
effectively right-shifted by those lost octal digits. And
this patch is again a strict improvement over that.
But if the size was between 8GB and 64GB, then our 12-byte
field held all of the actual digits, and only our NUL
terminator overflowed. According to POSIX, there should be a
NUL or space at the end of the field. However, GNU tar seems
to be lenient here, and will correctly parse a size up 64GB
(minus one) from the field. So sizes in this range might
have just worked, depending on the implementation reading
the tarfile.
This patch is mostly still an improvement there, as the 8GB
limit is specifically mentioned in POSIX as the correct
limit. But it's possible that it could be a regression
(versus the pre-f2f0267 state) if all of the following are
true:
1. You have a file between 8GB and 64GB.
2. Your tar implementation _doesn't_ know about pax
extended headers.
3. Your tar implementation _does_ parse 12-byte sizes from
the ustar header without a delimiter.
It's probably not worth worrying about such an obscure set
of conditions, but I'm documenting it here just in case.
Helped-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't/t5000-tar-tree.sh')
-rwxr-xr-x | t/t5000-tar-tree.sh | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 950bdd31e..93c2d3405 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -360,7 +360,7 @@ test_expect_success 'set up repository with huge blob' ' # We expect git to die with SIGPIPE here (otherwise we # would generate the whole 64GB). -test_expect_failure 'generate tar with huge size' ' +test_expect_success 'generate tar with huge size' ' { git archive HEAD echo $? >exit-code @@ -369,7 +369,7 @@ test_expect_failure 'generate tar with huge size' ' test_cmp expect exit-code ' -test_expect_failure TAR_HUGE 'system tar can read our huge size' ' +test_expect_success TAR_HUGE 'system tar can read our huge size' ' echo 68719476737 >expect && tar_info huge.tar | cut -d" " -f1 >actual && test_cmp expect actual |