diff options
author | Elliott Hughes <enh@google.com> | 2021-03-08 09:47:54 -0800 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2021-03-09 03:54:59 -0600 |
commit | 5c6628e724e9d3625f161db077b15b232e2ca096 (patch) | |
tree | 333fdc1b9038652017cd95aa94efedf29eda9f9a /toys/posix | |
parent | 668572a8650f3d4ff0fbe54ea07499b941244bdb (diff) | |
download | toybox-5c6628e724e9d3625f161db077b15b232e2ca096.tar.gz |
tar: fix base-256 output.
A tar file created by toybox tar with values large enough to need
base-256 rather than ASCII octal caused a tar reader to crash, and
caused GNU tar to complain.
I note from the docs at
https://github.com/libarchive/libarchive/blob/master/libarchive/tar.5#L326
that they imply that only the top *bit* should be set to indicate this
format, not the whole top byte, to give a 95-bit or 63-bit field. But I
don't think we can hit that in practice?
Bug: http://issuetracker.google.com/181683612
Diffstat (limited to 'toys/posix')
-rw-r--r-- | toys/posix/tar.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/toys/posix/tar.c b/toys/posix/tar.c index f31640c5..25dfc167 100644 --- a/toys/posix/tar.c +++ b/toys/posix/tar.c @@ -85,14 +85,19 @@ struct tar_hdr { prefix[155], padd[12]; }; +// Tar uses ASCII octal when it fits, base-256 otherwise. +#define ASCII_FITS(val, len) (!(val>>(3*(len-1)))) // convert from int to octal (or base-256) static void itoo(char *str, int len, unsigned long long val) { - // Do we need binary encoding? - if (!(val>>(3*(len-1)))) sprintf(str, "%0*llo", len-1, val); + if (ASCII_FITS(val, len)) sprintf(str, "%0*llo", len-1, val); else { + str += len; + while (len--) { + *--str = val; + val >>= 8; + } *str = 128; - while (--len) *++str = val>>(3*len); } } #define ITOO(x, y) itoo(x, sizeof(x), y) @@ -288,9 +293,11 @@ static int add_to_tar(struct dirtree *node) if (strlen(hname) > sizeof(hdr.name)) write_longname(hname, 'L'); if (!FLAG(numeric_owner)) { - if (TT.owner || (pw = bufgetpwuid(st->st_uid))) + if ((TT.owner || (pw = bufgetpwuid(st->st_uid))) && + ASCII_FITS(st->st_uid, sizeof(hdr.uid))) strncpy(hdr.uname, TT.owner ? TT.owner : pw->pw_name, sizeof(hdr.uname)); - if (TT.group || (gr = bufgetgrgid(st->st_gid))) + if ((TT.group || (gr = bufgetgrgid(st->st_gid))) && + ASCII_FITS(st->st_gid, sizeof(hdr.gid))) strncpy(hdr.gname, TT.group ? TT.group : gr->gr_name, sizeof(hdr.gname)); } |