libtar is a C library for manipulating POSIX tar files. It handles
adding and extracting files to/from a tar archive. I reviewed the
current Debian patches for usefulness and added all of them. Since the
"official unofficial" way (maintainer's words) to get new releases is
Git only I used the ptxdist mechanism for creating a tarball from a git
clone in get stage.

Signed-off-by: Alexander Dahl <p...@lespocky.de>
---
 ...d-using-a-static-buffer-in-th_get_pathnam.patch |   92 ++++
 patches/libtar-1.2.20/0002-no_maxpathlen.patch     |  487 ++++++++++++++++++++
 patches/libtar-1.2.20/0003-CVE-2013-4420.patch     |  126 +++++
 ...-th_get_size-macro-to-return-unsigned-int.patch |   51 ++
 patches/libtar-1.2.20/autogen.sh                   |    1 +
 patches/libtar-1.2.20/series                       |    7 +
 rules/libtar.in                                    |   11 +
 rules/libtar.make                                  |   62 +++
 8 files changed, 837 insertions(+)
 create mode 100644 
patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
 create mode 100644 patches/libtar-1.2.20/0002-no_maxpathlen.patch
 create mode 100644 patches/libtar-1.2.20/0003-CVE-2013-4420.patch
 create mode 100644 
patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
 create mode 120000 patches/libtar-1.2.20/autogen.sh
 create mode 100644 patches/libtar-1.2.20/series
 create mode 100644 rules/libtar.in
 create mode 100644 rules/libtar.make

diff --git 
a/patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
 
b/patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
new file mode 100644
index 0000000..7664f1d
--- /dev/null
+++ 
b/patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
@@ -0,0 +1,92 @@
+From: Kamil Dudka <kdu...@redhat.com>
+Date: Wed, 23 Oct 2013 13:04:22 +0200
+Subject: [PATCH] decode: avoid using a static buffer in th_get_pathname()
+
+decode: avoid using a static buffer in th_get_pathname()
+
+A solution suggested by Chris Frey:
+https://lists.feep.net:8080/pipermail/libtar/2013-October/000377.html
+
+Note this can break programs that expect sizeof(TAR) to be fixed.
+---
+ lib/decode.c |   25 ++++++++++++++++++-------
+ lib/handle.c |    1 +
+ lib/libtar.h |    3 +++
+ 3 files changed, 22 insertions(+), 7 deletions(-)
+
+diff --git a/lib/decode.c b/lib/decode.c
+index c16ea2d..35312be 100644
+--- a/lib/decode.c
++++ b/lib/decode.c
+@@ -13,6 +13,7 @@
+ #include <internal.h>
+ 
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <sys/param.h>
+ #include <pwd.h>
+ #include <grp.h>
+@@ -26,20 +27,30 @@
+ char *
+ th_get_pathname(TAR *t)
+ {
+-      static TLS_THREAD char filename[MAXPATHLEN];
+-
+       if (t->th_buf.gnu_longname)
+               return t->th_buf.gnu_longname;
+ 
+-      if (t->th_buf.prefix[0] != '\0')
++      /* allocate the th_pathname buffer if not already */
++      if (t->th_pathname == NULL)
++      {
++              t->th_pathname = malloc(MAXPATHLEN * sizeof(char));
++              if (t->th_pathname == NULL)
++                      /* out of memory */
++                      return NULL;
++      }
++
++      if (t->th_buf.prefix[0] == '\0')
++      {
++              snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name);
++      }
++      else
+       {
+-              snprintf(filename, sizeof(filename), "%.155s/%.100s",
++              snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s",
+                        t->th_buf.prefix, t->th_buf.name);
+-              return filename;
+       }
+ 
+-      snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name);
+-      return filename;
++      /* will be deallocated in tar_close() */
++      return t->th_pathname;
+ }
+ 
+ 
+diff --git a/lib/handle.c b/lib/handle.c
+index 33a262c..9faf2ed 100644
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -121,6 +121,7 @@ tar_close(TAR *t)
+               libtar_hash_free(t->h, ((t->oflags & O_ACCMODE) == O_RDONLY
+                                       ? free
+                                       : (libtar_freefunc_t)tar_dev_free));
++      free(t->th_pathname);
+       free(t);
+ 
+       return i;
+diff --git a/lib/libtar.h b/lib/libtar.h
+index 55f509a..5993cd2 100644
+--- a/lib/libtar.h
++++ b/lib/libtar.h
+@@ -85,6 +85,9 @@ typedef struct
+       int options;
+       struct tar_header th_buf;
+       libtar_hash_t *h;
++
++      /* introduced in libtar 1.2.21 */
++      char *th_pathname;
+ }
+ TAR;
+ 
diff --git a/patches/libtar-1.2.20/0002-no_maxpathlen.patch 
b/patches/libtar-1.2.20/0002-no_maxpathlen.patch
new file mode 100644
index 0000000..90a95fb
--- /dev/null
+++ b/patches/libtar-1.2.20/0002-no_maxpathlen.patch
@@ -0,0 +1,487 @@
+From: unknown author <unknown.aut...@example.com>
+Date: Thu, 20 Feb 2014 13:49:38 +0100
+Subject: [PATCH] no_maxpathlen
+
+---
+ compat/basename.c |   32 +++++++++++++++++-----
+ compat/dirname.c  |   14 +++++++++-
+ lib/append.c      |   21 +++++++++------
+ lib/decode.c      |    7 ++---
+ lib/util.c        |   38 +++++++++++++++++++-------
+ lib/wrapper.c     |   77 ++++++++++++++++++++++++++++++++++++++++++++---------
+ libtar/libtar.c   |   19 ++++++++++---
+ 7 files changed, 166 insertions(+), 42 deletions(-)
+
+diff --git a/compat/basename.c b/compat/basename.c
+index 2ac1e13..93c75e6 100644
+--- a/compat/basename.c
++++ b/compat/basename.c
+@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: basename.c,v 1.4 
1999/05/30 17:10:30 espie Exp
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/param.h>
++#include <stdlib.h>
+ 
+ char *
+ openbsd_basename(path)
+       const char *path;
+ {
+-      static char bname[MAXPATHLEN];
++      static char *bname = NULL;
++      static size_t allocated = 0;
+       register const char *endp, *startp;
++      int len = 0;
++
++      if (!allocated) {
++              allocated = 64;
++              bname = malloc(allocated);
++              if (!bname) {
++                      allocated = 0;
++                      return NULL;
++              }
++      }
+ 
+       /* Empty or NULL string gets treated as "." */
+       if (path == NULL || *path == '\0') {
+@@ -64,11 +76,19 @@ openbsd_basename(path)
+       while (startp > path && *(startp - 1) != '/')
+               startp--;
+ 
+-      if (endp - startp + 1 > sizeof(bname)) {
+-              errno = ENAMETOOLONG;
+-              return(NULL);
++      len = endp - startp + 1;
++
++      if (len + 1 > allocated) {
++              size_t new_allocated = 2*(len+1);
++              void *new_bname = malloc(new_allocated);
++              if (!new_bname)
++                      return NULL;
++              allocated = new_allocated;
++              free(bname);
++              bname = new_bname;
+       }
+-      (void)strncpy(bname, startp, endp - startp + 1);
+-      bname[endp - startp + 1] = '\0';
++
++      (void)strncpy(bname, startp, len);
++      bname[len] = '\0';
+       return(bname);
+ }
+diff --git a/compat/dirname.c b/compat/dirname.c
+index 986db4a..987b46e 100644
+--- a/compat/dirname.c
++++ b/compat/dirname.c
+@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: dirname.c,v 1.4 
1999/05/30 17:10:30 espie Exp $
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/param.h>
++#include <stdlib.h>
+ 
+ char *
+ openbsd_dirname(path)
+       const char *path;
+ {
+-      static char bname[MAXPATHLEN];
++      static char *bname = NULL;
++      static size_t allocated = 0;
+       register const char *endp;
++      int len;
++
++      if (!allocated) {
++              allocated = 64;
++              bname = malloc(allocated);
++              if (!bname) {
++                      allocated = 0;
++                      return NULL;
++              }
++      }
+ 
+       /* Empty or NULL string gets treated as "." */
+       if (path == NULL || *path == '\0') {
+diff --git a/lib/append.c b/lib/append.c
+index 13e1ace..3628d87 100644
+--- a/lib/append.c
++++ b/lib/append.c
+@@ -38,7 +38,7 @@ typedef struct tar_dev tar_dev_t;
+ struct tar_ino
+ {
+       ino_t ti_ino;
+-      char ti_name[MAXPATHLEN];
++      char ti_name[];
+ };
+ typedef struct tar_ino tar_ino_t;
+ 
+@@ -61,7 +61,7 @@ tar_append_file(TAR *t, const char *realname, const char 
*savename)
+       libtar_hashptr_t hp;
+       tar_dev_t *td = NULL;
+       tar_ino_t *ti = NULL;
+-      char path[MAXPATHLEN];
++      char *path = NULL;
+ 
+ #ifdef DEBUG
+       printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
+@@ -126,34 +126,39 @@ tar_append_file(TAR *t, const char *realname, const char 
*savename)
+       }
+       else
+       {
++              const char *name;
+ #ifdef DEBUG
+               printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
+                      "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev),
+                      s.st_ino, realname);
+ #endif
+-              ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t));
++              name = savename ? savename : realname;
++              ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t) + strlen(name) + 
1);
+               if (ti == NULL)
+                       return -1;
+               ti->ti_ino = s.st_ino;
+-              snprintf(ti->ti_name, sizeof(ti->ti_name), "%s",
+-                       savename ? savename : realname);
++              snprintf(ti->ti_name, strlen(name) + 1, "%s", name);
+               libtar_hash_add(td->td_h, ti);
+       }
+ 
+       /* check if it's a symlink */
+       if (TH_ISSYM(t))
+       {
+-              i = readlink(realname, path, sizeof(path));
++              if ((path = malloc(s.st_size + 1)) == NULL)
++                      return -1;
++              i = readlink(realname, path, s.st_size);
+               if (i == -1)
++              {
++                      free(path);
+                       return -1;
+-              if (i >= MAXPATHLEN)
+-                      i = MAXPATHLEN - 1;
++              }
+               path[i] = '\0';
+ #ifdef DEBUG
+               printf("    tar_append_file(): encoding symlink \"%s\" -> "
+                      "\"%s\"...\n", realname, path);
+ #endif
+               th_set_link(t, path);
++              free(path);
+       }
+ 
+       /* print file info */
+diff --git a/lib/decode.c b/lib/decode.c
+index 35312be..df62bec 100644
+--- a/lib/decode.c
++++ b/lib/decode.c
+@@ -33,7 +33,8 @@ th_get_pathname(TAR *t)
+       /* allocate the th_pathname buffer if not already */
+       if (t->th_pathname == NULL)
+       {
+-              t->th_pathname = malloc(MAXPATHLEN * sizeof(char));
++              /* Allocate the maximum length of prefix + '/' + name + '\0' */
++              t->th_pathname = malloc(155 + 1 + 100 + 1);
+               if (t->th_pathname == NULL)
+                       /* out of memory */
+                       return NULL;
+@@ -41,11 +42,11 @@ th_get_pathname(TAR *t)
+ 
+       if (t->th_buf.prefix[0] == '\0')
+       {
+-              snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name);
++              sprintf(t->th_pathname, "%.100s", t->th_buf.name);
+       }
+       else
+       {
+-              snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s",
++              sprintf(t->th_pathname, "%.155s/%.100s",
+                        t->th_buf.prefix, t->th_buf.name);
+       }
+ 
+diff --git a/lib/util.c b/lib/util.c
+index 31e8315..2c9b0fa 100644
+--- a/lib/util.c
++++ b/lib/util.c
+@@ -15,6 +15,7 @@
+ #include <stdio.h>
+ #include <sys/param.h>
+ #include <errno.h>
++#include <stdlib.h>
+ 
+ #ifdef STDC_HEADERS
+ # include <string.h>
+@@ -25,13 +26,15 @@
+ int
+ path_hashfunc(char *key, int numbuckets)
+ {
+-      char buf[MAXPATHLEN];
++      char *buf;
+       char *p;
++      int i;
+ 
+-      strcpy(buf, key);
++      buf = strdup(key);
+       p = basename(buf);
+-
+-      return (((unsigned int)p[0]) % numbuckets);
++      i = ((unsigned int)p[0]) % numbuckets;
++      free(buf);
++      return (i);
+ }
+ 
+ 
+@@ -77,15 +80,26 @@ ino_hash(ino_t *inode)
+ int
+ mkdirhier(char *path)
+ {
+-      char src[MAXPATHLEN], dst[MAXPATHLEN] = "";
+-      char *dirp, *nextp = src;
+-      int retval = 1;
++      char *src, *dst = NULL;
++      char *dirp, *nextp = NULL;
++      int retval = 1, len;
++
++      len = strlen(path);
++      if ((src = strdup(path)) == NULL)
++      {
++              errno = ENOMEM;
++              return -1;
++      }
++      nextp = src;
+ 
+-      if (strlcpy(src, path, sizeof(src)) > sizeof(src))
++      /* Make room for // with absolute paths */
++      if ((dst = malloc(len + 2)) == NULL)
+       {
+-              errno = ENAMETOOLONG;
++              free(src);
++              errno = ENOMEM;
+               return -1;
+       }
++      dst[0] = '\0';
+ 
+       if (path[0] == '/')
+               strcpy(dst, "/");
+@@ -102,12 +116,18 @@ mkdirhier(char *path)
+               if (mkdir(dst, 0777) == -1)
+               {
+                       if (errno != EEXIST)
++                      {
++                              free(src);
++                              free(dst);
+                               return -1;
++                      }
+               }
+               else
+                       retval = 0;
+       }
+ 
++      free(src);
++      free(dst);
+       return retval;
+ }
+ 
+diff --git a/lib/wrapper.c b/lib/wrapper.c
+index 4cd0652..897ee44 100644
+--- a/lib/wrapper.c
++++ b/lib/wrapper.c
+@@ -16,6 +16,7 @@
+ #include <sys/param.h>
+ #include <dirent.h>
+ #include <errno.h>
++#include <stdlib.h>
+ 
+ #ifdef STDC_HEADERS
+ # include <string.h>
+@@ -26,8 +27,8 @@ int
+ tar_extract_glob(TAR *t, char *globname, char *prefix)
+ {
+       char *filename;
+-      char buf[MAXPATHLEN];
+-      int i;
++      char *buf = NULL;
++      int i, len;
+ 
+       while ((i = th_read(t)) == 0)
+       {
+@@ -41,11 +42,25 @@ tar_extract_glob(TAR *t, char *globname, char *prefix)
+               if (t->options & TAR_VERBOSE)
+                       th_print_long_ls(t);
+               if (prefix != NULL)
+-                      snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
++              {
++                      len = strlen(prefix) + 1 + strlen(filename);
++                      if ((buf = malloc(len + 1)) == NULL)
++                              return -1;
++                      sprintf(buf, "%s/%s", prefix, filename);
++              }
+               else
+-                      strlcpy(buf, filename, sizeof(buf));
++              {
++                      len = strlen(filename);
++                      if ((buf = malloc(len + 1)) == NULL)
++                              return -1;
++                      strcpy(buf, filename);
++              }
+               if (tar_extract_file(t, buf) != 0)
++              {
++                      free(buf);
+                       return -1;
++              }
++              free(buf);
+       }
+ 
+       return (i == 1 ? 0 : -1);
+@@ -56,8 +71,9 @@ int
+ tar_extract_all(TAR *t, char *prefix)
+ {
+       char *filename;
+-      char buf[MAXPATHLEN];
+-      int i;
++      char *buf = NULL;
++      size_t bufsize = 0;
++      int i, len;
+ 
+ #ifdef DEBUG
+       printf("==> tar_extract_all(TAR *t, \"%s\")\n",
+@@ -73,15 +89,29 @@ tar_extract_all(TAR *t, char *prefix)
+               if (t->options & TAR_VERBOSE)
+                       th_print_long_ls(t);
+               if (prefix != NULL)
+-                      snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
++              {
++                      len = strlen(prefix) + 1 + strlen(filename);
++                      if ((buf = malloc(len + 1)) == NULL)
++                              return -1;
++                      sprintf(buf, "%s/%s", prefix, filename);
++              }
+               else
+-                      strlcpy(buf, filename, sizeof(buf));
++              {
++                      len = strlen(filename);
++                      if ((buf = malloc(len + 1)) == NULL)
++                              return -1;
++                      strcpy(buf, filename);
++              }
+ #ifdef DEBUG
+               printf("    tar_extract_all(): calling tar_extract_file(t, "
+                      "\"%s\")\n", buf);
+ #endif
+               if (tar_extract_file(t, buf) != 0)
++              {
++                      free(buf);
+                       return -1;
++              }
++              free(buf);
+       }
+ 
+       return (i == 1 ? 0 : -1);
+@@ -91,11 +121,14 @@ tar_extract_all(TAR *t, char *prefix)
+ int
+ tar_append_tree(TAR *t, char *realdir, char *savedir)
+ {
+-      char realpath[MAXPATHLEN];
+-      char savepath[MAXPATHLEN];
++      char *realpath = NULL;
++      size_t realpathsize = 0;
++      char *savepath = NULL;
++      size_t savepathsize = 0;
+       struct dirent *dent;
+       DIR *dp;
+       struct stat s;
++      int len;
+ 
+ #ifdef DEBUG
+       printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n",
+@@ -122,11 +155,21 @@ tar_append_tree(TAR *t, char *realdir, char *savedir)
+                   strcmp(dent->d_name, "..") == 0)
+                       continue;
+ 
+-              snprintf(realpath, MAXPATHLEN, "%s/%s", realdir,
++              len = strlen(realdir) + 1 + strlen(dent->d_name);
++              if ((realpath = malloc(len + 1)) == NULL)
++                      return -1;
++              snprintf(realpath, len + 1, "%s/%s", realdir,
+                        dent->d_name);
+               if (savedir)
+-                      snprintf(savepath, MAXPATHLEN, "%s/%s", savedir,
++              {
++                      len = strlen(savedir) + 1 + strlen(dent->d_name);
++                      if ((savepath = malloc(len + 1)) == NULL) {
++                              free(realpath);
++                              return -1;
++                      }
++                      snprintf(savepath, len + 1, "%s/%s", savedir,
+                                dent->d_name);
++              }
+ 
+               if (lstat(realpath, &s) != 0)
+                       return -1;
+@@ -135,13 +178,23 @@ tar_append_tree(TAR *t, char *realdir, char *savedir)
+               {
+                       if (tar_append_tree(t, realpath,
+                                           (savedir ? savepath : NULL)) != 0)
++                      {
++                              free(realpath);
++                              free(savepath);
+                               return -1;
++                      }
+                       continue;
+               }
+ 
+               if (tar_append_file(t, realpath,
+                                   (savedir ? savepath : NULL)) != 0)
++              {
++                      free(realpath);
++                      free(savepath);
+                       return -1;
++              }
++              free(realpath);
++              free(savepath);
+       }
+ 
+       closedir(dp);
+diff --git a/libtar/libtar.c b/libtar/libtar.c
+index 9fa92b2..f4967e8 100644
+--- a/libtar/libtar.c
++++ b/libtar/libtar.c
+@@ -111,8 +111,9 @@ create(char *tarfile, char *rootdir, libtar_list_t *l)
+ {
+       TAR *t;
+       char *pathname;
+-      char buf[MAXPATHLEN];
++      char *buf = NULL;
+       libtar_listptr_t lp;
++      int len;
+ 
+       if (tar_open(&t, tarfile,
+ #ifdef HAVE_LIBZ
+@@ -133,17 +134,29 @@ create(char *tarfile, char *rootdir, libtar_list_t *l)
+       {
+               pathname = (char *)libtar_listptr_data(&lp);
+               if (pathname[0] != '/' && rootdir != NULL)
+-                      snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
++              {
++                      len = strlen(rootdir) + 1 + strlen(pathname);
++                      if ((buf = malloc(len + 1)) == NULL)
++                              return -1;
++                      snprintf(buf, len + 1, "%s/%s", rootdir, pathname);
++              }
+               else
+-                      strlcpy(buf, pathname, sizeof(buf));
++              {
++                      len = strlen(pathname);
++                      if ((buf = malloc(len + 1)) == NULL)
++                              return -1;
++                      strlcpy(buf, pathname, len + 1);
++              }
+               if (tar_append_tree(t, buf, pathname) != 0)
+               {
+                       fprintf(stderr,
+                               "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
+                               pathname, strerror(errno));
+                       tar_close(t);
++                      free(buf);
+                       return -1;
+               }
++              free(buf);
+       }
+ 
+       if (tar_append_eof(t) != 0)
diff --git a/patches/libtar-1.2.20/0003-CVE-2013-4420.patch 
b/patches/libtar-1.2.20/0003-CVE-2013-4420.patch
new file mode 100644
index 0000000..7adbaed
--- /dev/null
+++ b/patches/libtar-1.2.20/0003-CVE-2013-4420.patch
@@ -0,0 +1,126 @@
+From: unknown author <unknown.aut...@example.com>
+Date: Thu, 20 Feb 2014 13:49:38 +0100
+Subject: [PATCH] CVE-2013-4420
+
+---
+ lib/decode.c   |   33 +++++++++++++++++++++++++++++++--
+ lib/extract.c  |    8 ++++----
+ lib/internal.h |    1 +
+ lib/output.c   |    4 ++--
+ 4 files changed, 38 insertions(+), 8 deletions(-)
+
+diff --git a/lib/decode.c b/lib/decode.c
+index df62bec..0b75be1 100644
+--- a/lib/decode.c
++++ b/lib/decode.c
+@@ -22,13 +22,42 @@
+ # include <string.h>
+ #endif
+ 
++char *
++safer_name_suffix (char const *file_name)
++{
++      char const *p, *t;
++      p = t = file_name;
++      while (*p == '/') t = ++p;
++      while (*p)
++      {
++              while (p[0] == '.' && p[0] == p[1] && p[2] == '/')
++              {
++                      p += 3;
++                      t = p;
++              }
++              /* advance pointer past the next slash */
++              while (*p && (p++)[0] != '/');
++      }
++
++      if (!*t)
++      {
++              t = ".";
++      }
++
++      if (t != file_name)
++      {
++              /* TODO: warn somehow that the path was modified */
++      }
++      return (char*)t;
++}
++
+ 
+ /* determine full path name */
+ char *
+ th_get_pathname(TAR *t)
+ {
+       if (t->th_buf.gnu_longname)
+-              return t->th_buf.gnu_longname;
++              return safer_name_suffix(t->th_buf.gnu_longname);
+ 
+       /* allocate the th_pathname buffer if not already */
+       if (t->th_pathname == NULL)
+@@ -51,7 +80,7 @@ th_get_pathname(TAR *t)
+       }
+ 
+       /* will be deallocated in tar_close() */
+-      return t->th_pathname;
++      return safer_name_suffix(t->th_pathname);
+ }
+ 
+ 
+diff --git a/lib/extract.c b/lib/extract.c
+index 36357e7..627e05f 100644
+--- a/lib/extract.c
++++ b/lib/extract.c
+@@ -298,14 +298,14 @@ tar_extract_hardlink(TAR * t, char *realname)
+       if (mkdirhier(dirname(filename)) == -1)
+               return -1;
+       libtar_hashptr_reset(&hp);
+-      if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
++      if (libtar_hash_getkey(t->h, &hp, safer_name_suffix(th_get_linkname(t)),
+                              (libtar_matchfunc_t)libtar_str_match) != 0)
+       {
+               lnp = (char *)libtar_hashptr_data(&hp);
+               linktgt = &lnp[strlen(lnp) + 1];
+       }
+       else
+-              linktgt = th_get_linkname(t);
++              linktgt = safer_name_suffix(th_get_linkname(t));
+ 
+ #ifdef DEBUG
+       printf("  ==> extracting: %s (link to %s)\n", filename, linktgt);
+@@ -343,9 +343,9 @@ tar_extract_symlink(TAR *t, char *realname)
+ 
+ #ifdef DEBUG
+       printf("  ==> extracting: %s (symlink to %s)\n",
+-             filename, th_get_linkname(t));
++             filename, safer_name_suffix(th_get_linkname(t)));
+ #endif
+-      if (symlink(th_get_linkname(t), filename) == -1)
++      if (symlink(safer_name_suffix(th_get_linkname(t)), filename) == -1)
+       {
+ #ifdef DEBUG
+               perror("symlink()");
+diff --git a/lib/internal.h b/lib/internal.h
+index da7be7f..f05ca4f 100644
+--- a/lib/internal.h
++++ b/lib/internal.h
+@@ -21,3 +21,4 @@
+ #define TLS_THREAD
+ #endif
+ 
++char* safer_name_suffix(char const*);
+diff --git a/lib/output.c b/lib/output.c
+index a2db929..99421bd 100644
+--- a/lib/output.c
++++ b/lib/output.c
+@@ -123,9 +123,9 @@ th_print_long_ls(TAR *t)
+               else
+                       printf(" link to ");
+               if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL)
+-                      printf("%s", t->th_buf.gnu_longlink);
++                      printf("%s", safer_name_suffix(t->th_buf.gnu_longlink));
+               else
+-                      printf("%.100s", t->th_buf.linkname);
++                      printf("%.100s", safer_name_suffix(t->th_buf.linkname));
+       }
+ 
+       putchar('\n');
diff --git 
a/patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
 
b/patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
new file mode 100644
index 0000000..8cc3a41
--- /dev/null
+++ 
b/patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
@@ -0,0 +1,51 @@
+From: Chris Frey <cdf...@foursquare.net>
+Date: Thu, 24 Oct 2013 18:52:44 -0400
+Subject: [PATCH] Change th_get_size() macro to return unsigned int
+
+On systems where size_t is larger than an int (and larger than
+unsigned int), then in various places in the library, where
+stuff like this happens:
+
+       size_t sz = th_get_size(t);
+
+then the int value returned from th_get_size() is sign extended to
+some unwieldy amount.
+
+On 64bit systems, this can yield extremely large values.
+
+By fixing this problem in the header, and only for th_get_size(),
+we avoid breaking the API of the function call oct_to_int()
+(which arguably should return an unsigned int, since the sscanf()
+it uses expects to yield an unsigned int).  We also fix the library,
+which uses th_get_size() internally to assign sizes to size_t.
+
+The drawback is that not all client code that uses th_get_size()
+will be fixed, until they recompile, but they will automatically
+take advantage of the bugs fixed *inside* the library.
+
+The remaining th_get_*() functions operate on modes and CRC values
+and the like, and should be fine, remaining as ints.
+
+Thanks very much to Magnus Holmgren for catching this behaviour.
+https://lists.feep.net:8080/pipermail/libtar/2013-October/000365.html
+---
+ lib/libtar.h |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/lib/libtar.h b/lib/libtar.h
+index 5993cd2..b3281f7 100644
+--- a/lib/libtar.h
++++ b/lib/libtar.h
+@@ -183,7 +183,11 @@ int th_write(TAR *t);
+ 
+ /* decode tar header info */
+ #define th_get_crc(t) oct_to_int((t)->th_buf.chksum)
+-#define th_get_size(t) oct_to_int((t)->th_buf.size)
++/* We cast from int (what oct_to_int() returns) to
++   unsigned int, to avoid unwieldy sign extensions
++   from occurring on systems where size_t is bigger than int,
++   since th_get_size() is often stored into a size_t. */
++#define th_get_size(t) ((unsigned int)oct_to_int((t)->th_buf.size))
+ #define th_get_mtime(t) oct_to_int((t)->th_buf.mtime)
+ #define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor)
+ #define th_get_devminor(t) oct_to_int((t)->th_buf.devminor)
diff --git a/patches/libtar-1.2.20/autogen.sh b/patches/libtar-1.2.20/autogen.sh
new file mode 120000
index 0000000..9f8a4cb
--- /dev/null
+++ b/patches/libtar-1.2.20/autogen.sh
@@ -0,0 +1 @@
+../autogen.sh
\ No newline at end of file
diff --git a/patches/libtar-1.2.20/series b/patches/libtar-1.2.20/series
new file mode 100644
index 0000000..2af0ad9
--- /dev/null
+++ b/patches/libtar-1.2.20/series
@@ -0,0 +1,7 @@
+# generated by git-ptx-patches
+#tag:base --start-number 1
+0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
+0002-no_maxpathlen.patch
+0003-CVE-2013-4420.patch
+0004-Change-th_get_size-macro-to-return-unsigned-int.patch
+# 8d73710ff3b5b805b75c941056495d29  - git-ptx-patches magic
diff --git a/rules/libtar.in b/rules/libtar.in
new file mode 100644
index 0000000..d8a800d
--- /dev/null
+++ b/rules/libtar.in
@@ -0,0 +1,11 @@
+## SECTION=system_libraries
+
+config LIBTAR
+       tristate
+       prompt "libtar"
+       select ZLIB
+       help
+         libtar is a C library for manipulating POSIX tar files. It handles
+         adding and extracting files to/from a tar archive.
+
+# vim: ft=kconfig noet tw=72
diff --git a/rules/libtar.make b/rules/libtar.make
new file mode 100644
index 0000000..2434822
--- /dev/null
+++ b/rules/libtar.make
@@ -0,0 +1,62 @@
+# -*-makefile-*-
+#
+# Copyright (C) 2014 by Alexander Dahl <p...@lespocky.de>
+#
+# See CREDITS for details about who has contributed to this project.
+#
+# For further information about the PTXdist project and license conditions
+# see the README file.
+#
+
+#
+# We provide this package
+#
+PACKAGES-$(PTXCONF_LIBTAR) += libtar
+
+#
+# Paths and names
+#
+LIBTAR_VERSION := 1.2.20
+LIBTAR_MD5             := dcdcdf8cfbbd3df3862198b0897071b6
+LIBTAR         := libtar-$(LIBTAR_VERSION)
+LIBTAR_SUFFIX  := tar.gz
+LIBTAR_URL             := git://repo.or.cz/libtar.git;tag=v$(LIBTAR_VERSION)
+LIBTAR_SOURCE  := $(SRCDIR)/$(LIBTAR).$(LIBTAR_SUFFIX)
+LIBTAR_DIR             := $(BUILDDIR)/$(LIBTAR)
+LIBTAR_LICENSE := unknown
+
+# ----------------------------------------------------------------------------
+# Prepare
+# ----------------------------------------------------------------------------
+
+#LIBTAR_CONF_ENV       := $(CROSS_ENV)
+
+#
+# autoconf
+#
+LIBTAR_CONF_TOOL       := autoconf
+LIBTAR_CONF_OPT        := $(CROSS_AUTOCONF_USR) \
+       --disable-encap \
+       --disable-epkg-install \
+       --with-zlib=$(SYSROOT)
+
+# ----------------------------------------------------------------------------
+# Target-Install
+# ----------------------------------------------------------------------------
+
+$(STATEDIR)/libtar.targetinstall:
+       @$(call targetinfo)
+
+       @$(call install_init, libtar)
+       @$(call install_fixup, libtar,PRIORITY,optional)
+       @$(call install_fixup, libtar,SECTION,base)
+       @$(call install_fixup, libtar,AUTHOR,"Alexander Dahl 
<p...@lespocky.de>")
+       @$(call install_fixup, libtar,DESCRIPTION,missing)
+
+       @$(call install_lib, libtar, 0, 0, 0644, libtar)
+
+       @$(call install_finish, libtar)
+
+       @$(call touch)
+
+# vim: ft=make noet
-- 
1.7.10.4


-- 
ptxdist mailing list
ptxdist@pengutronix.de

Reply via email to