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);
 	}

Reply via email to