From: René Scharfe <hidden> Date: 2019-08-17 16:19:44
The code for building pax extended headers has been miscalculating
lengths slightly shorter than powers of 10 since I wrote it in 2006.
That affects entries for paths with a length of 990, 991, 9989, 9990,
9991, 99988 etc. and link targets 4 characters shorter. Here's a
series for fixing it.
archive-tar: report wrong pax extended header length
archive-tar: fix pax extended header length calculation
archive-tar: use size_t in strbuf_append_ext_header()
archive-tar: turn length miscalculation warning into BUG
archive-tar.c | 14 ++++++++++----
t/t5004-archive-corner-cases.sh | 19 +++++++++++++++++++
2 files changed, 29 insertions(+), 4 deletions(-)
--
2.23.0
From: René Scharfe <hidden> Date: 2019-08-17 16:24:01
Extended header entries contain a length value that is a bit tricky to
calculate because it includes its own length (number of decimal digits)
as well. We get it wrong in corner cases. Add a check, report wrong
results as a warning and add a test for exercising it.
Signed-off-by: René Scharfe <redacted>
---
archive-tar.c | 6 ++++++
t/t5004-archive-corner-cases.sh | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+)
From: René Scharfe <hidden> Date: 2019-08-17 16:24:07
A pax extended header records starts with a decimal number. Its value
is the length of the whole record, including its own length.
The calculation of that number if strbuf_append_ext_header() is off by
one in case the length of the rest is close to a higher order of
magnitude. This affects paths and link targets a bit shorter than 1000,
10000, 100000 etc. characters -- paths with a length of up to 100 fit
into the tar header and don't need a pax extended header.
The mistake has been present since the function was added by ae64bbc18c
("tar-tree: Introduce write_entry()", 2006-03-25).
Account for digits added to len during the loop and keep incrementing
until we have enough space for len and the rest. The crucial change is
to check against the current value of len before each iteration, instead
of against its value before the loop.
Signed-off-by: René Scharfe <redacted>
---
archive-tar.c | 2 +-
t/t5004-archive-corner-cases.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
@@ -217,7 +217,7 @@ build_tree() {'"$1"}-test_expect_failure'tar archive with long paths''+test_expect_success'tar archive with long paths''blob=$(echofoo|githash-object-w--stdin)&&tree=$(build_tree$blob|gitmktree)&&gitarchive-olong_paths.tar$tree2>stderr&&--
From: René Scharfe <hidden> Date: 2019-08-17 16:24:17
One of its callers already passes in a size_t value. Use it
consistently in this function.
Signed-off-by: René Scharfe <redacted>
---
archive-tar.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
From: René Scharfe <hidden> Date: 2019-08-17 16:24:28
Now that we're confident our pax extended header calculation is correct,
turn the criticality of the assertion up to the maximum, from warning
right up to BUG. Simplify the test, as the stderr comparison step would
not be reached in case the BUG message is triggered.
Signed-off-by: René Scharfe <redacted>
---
archive-tar.c | 6 +++---
t/t5004-archive-corner-cases.sh | 3 +--
2 files changed, 4 insertions(+), 5 deletions(-)
@@ -158,9 +158,9 @@ static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword,strbuf_addch(sb,'\n');if(len!=sb->len-orig_len)-warning("pax extended header length miscalculated as %"PRIuMAX-", should be %"PRIuMAX,-(uintmax_t)len,(uintmax_t)(sb->len-orig_len));+BUG("pax extended header length miscalculated as %"PRIuMAX+", should be %"PRIuMAX,+(uintmax_t)len,(uintmax_t)(sb->len-orig_len));}/*
From: brian m. carlson <hidden> Date: 2019-08-17 16:40:43
On 2019-08-17 at 16:19:29, René Scharfe wrote:
The code for building pax extended headers has been miscalculating
lengths slightly shorter than powers of 10 since I wrote it in 2006.
That affects entries for paths with a length of 990, 991, 9989, 9990,
9991, 99988 etc. and link targets 4 characters shorter. Here's a
series for fixing it.
This series looked good to me. I'm don't completely understand our
technique for computing the length, but the additional tests build my
confidence and your explanation makes sense.
As a side note, I have personally found computing the length of pax
headers to be enormously difficult due to this very edge case, so I'm
not surprised this bug crept in.
--
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
From: Eric Sunshine <hidden> Date: 2019-08-17 18:05:34
On Sat, Aug 17, 2019 at 12:24 PM René Scharfe [off-list ref] wrote:
A pax extended header records starts with a decimal number. Its value
s/records/record/
is the length of the whole record, including its own length.
The calculation of that number if strbuf_append_ext_header() is off by
s/if/in/
one in case the length of the rest is close to a higher order of
magnitude. This affects paths and link targets a bit shorter than 1000,
10000, 100000 etc. characters -- paths with a length of up to 100 fit
into the tar header and don't need a pax extended header.
The mistake has been present since the function was added by ae64bbc18c
("tar-tree: Introduce write_entry()", 2006-03-25).
Account for digits added to len during the loop and keep incrementing
until we have enough space for len and the rest. The crucial change is
to check against the current value of len before each iteration, instead
of against its value before the loop.
Signed-off-by: René Scharfe <redacted>