Package: libtar0 Version: 1.2.20-4 Severity: normal Tags: patch Hi,
The old-style GNU header format (used before GNU tar 1.12) looks very much like the POSIX format, except that there is no “prefix” field, and those bytes are used for other fields, such as mtime, ctime, multi-volume support and so on. One would think that this format is now long irrelevant, but unfortunately, tar automatically switches to these headers when making incremental archives (whether old-style or new-style incremental archives). Thus, when libtar looks at such an archive, it will misinterpret these headers as a prefix field, and extract things such as “12411637142/./foo.c” and the likes (unless they are above 100 bytes, in which case the GNU-style name takes over!). I've attached a simple patch to fix this; it doesn't give access to all the other fields, but at least it fixes th_get_pathname() (which seems to be pretty much the only place the prefix field is actually interpreted) so that it does not return these bogus paths. -- System Information: Debian Release: jessie/sid APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 3.16.3 (SMP w/4 CPU cores) Locale: LANG=nb_NO.utf8, LC_CTYPE=nb_NO.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages libtar0 depends on: ii libc6 2.19-11 libtar0 recommends no packages. libtar0 suggests no packages. -- no debconf information
Index: libtar-1.2.20/lib/decode.c =================================================================== --- libtar-1.2.20.orig/lib/decode.c +++ libtar-1.2.20/lib/decode.c @@ -69,7 +69,15 @@ th_get_pathname(TAR *t) return NULL; } - if (t->th_buf.prefix[0] == '\0') + /* + * Old GNU headers use the POSIX prefix field for many other things, + * such as mtime and ctime. The only robust way to distinguish + * old GNU versus new GNU/POSIX is that old GNU does not clear unknown + * bits (in particular S_IFREG) from the mode field, so we test for + * those. This is the same heuristic as GNU tar uses itself. + */ + if ((oct_to_int(t->th_buf.mode) & ~07777) == 0 && + t->th_buf.prefix[0] == '\0') { sprintf(t->th_pathname, "%.100s", t->th_buf.name); }