aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-05-18 14:00:31 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-05-18 14:00:31 +0200
commit692cbd0079658a8eb048c9b00dadec2d69d28b14 (patch)
treedafc0801eb08bde9674ed0543d3c091c00442543
parentbf1ebf7c7989bf95307f594e6ea715fc1f7c3a1c (diff)
libtar: fix size computation of PAX line length
This commit attempts to fix the following two problems: - The number of digits computation returning an off-by-one result if the number is 10, or the resulting digit string starts with "10". This results in one-too-many padding bytes, corrupting the rest of the archive since the headers now don't start at multiples of 512 anymore. - Adding the line length prefix affects the line length (duh). If it grows far enough to require more digits, the result is a similar problem. This is a converging series that we need to compute the limit of. Unit tests for this still need to be added. Or maybe I can convince a bored undergrad student to provide an induction proof. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--lib/tar/write_header.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/lib/tar/write_header.c b/lib/tar/write_header.c
index cd65f59..aaf9f08 100644
--- a/lib/tar/write_header.c
+++ b/lib/tar/write_header.c
@@ -116,7 +116,7 @@ static size_t num_digits(size_t num)
{
size_t i = 1;
- while (num > 10) {
+ while (num >= 10) {
num /= 10;
++i;
}
@@ -124,6 +124,18 @@ static size_t num_digits(size_t num)
return i;
}
+static size_t prefix_digit_len(size_t len)
+{
+ size_t old_ndigit, ndigit = 0;
+
+ do {
+ old_ndigit = ndigit;
+ ndigit = num_digits(len + ndigit);
+ } while (old_ndigit != ndigit);
+
+ return ndigit;
+}
+
static int write_schily_xattr(FILE *fp, const struct stat *orig,
const char *name, const tar_xattr_t *xattr)
{
@@ -133,9 +145,9 @@ static int write_schily_xattr(FILE *fp, const struct stat *orig,
struct stat sb;
for (it = xattr; it != NULL; it = it->next) {
- len = strlen(prefix) + strlen(it->key) + it->value_len + 2;
+ len = strlen(prefix) + strlen(it->key) + it->value_len + 3;
- total_size += num_digits(len) + 1 + len;
+ total_size += len + prefix_digit_len(len);
}
sb = *orig;
@@ -146,8 +158,8 @@ static int write_schily_xattr(FILE *fp, const struct stat *orig,
return -1;
for (it = xattr; it != NULL; it = it->next) {
- len = strlen(prefix) + strlen(it->key) + it->value_len + 2;
- len += num_digits(len) + 1;
+ len = strlen(prefix) + strlen(it->key) + it->value_len + 3;
+ len += prefix_digit_len(len);
fprintf(fp, PRI_SZ " %s%s=", len, prefix, it->key);
fwrite(it->value, 1, it->value_len, fp);