Subversion Repositories

?revision_form?Rev ?revision_input??revision_submit??revision_endform?

Blame | Last modification | View Log | RSS feed

Description: Fix memory leaks related to th_get_pathname()
Author: James Morrison <phython@debian.org>
Author: Martin Gadbois <martin.gadbois@colubris.com>
Author: Magnus Holmgren <holmgren@debian.org>
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libtar/+bug/41804

--- a/lib/wrapper.c
+++ b/lib/wrapper.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 
 #ifdef STDC_HEADERS
+# include <stdlib.h>
 # include <string.h>
 #endif
 
@@ -35,7 +36,10 @@ tar_extract_glob(TAR *t, char *globname,
                if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD))
                {
                        if (TH_ISREG(t) && tar_skip_regfile(t))
+                       {
+                               free(filename);
                                return -1;
+                       }
                        continue;
                }
                if (t->options & TAR_VERBOSE)
@@ -45,7 +49,11 @@ tar_extract_glob(TAR *t, char *globname,
                else
                        strlcpy(buf, filename, sizeof(buf));
                if (tar_extract_file(t, filename) != 0)
+               {
+                       free(filename);
                        return -1;
+               }
+               free(filename);
        }
 
        return (i == 1 ? 0 : -1);
@@ -76,12 +84,17 @@ tar_extract_all(TAR *t, char *prefix)
                        snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
                else
                        strlcpy(buf, filename, sizeof(buf));
+               free(filename);
 #ifdef DEBUG
                printf("    tar_extract_all(): calling tar_extract_file(t, "
                       "\"%s\")\n", buf);
 #endif
                if (tar_extract_file(t, buf) != 0)
+               {
+                       free(filename);
                        return -1;
+               }
+               free(filename);
        }
 
        return (i == 1 ? 0 : -1);
--- a/lib/extract.c
+++ b/lib/extract.c
@@ -21,6 +21,7 @@
 
 #ifdef STDC_HEADERS
 # include <stdlib.h>
+# include <string.h>
 #endif
 
 #ifdef HAVE_UNISTD_H
@@ -43,9 +44,10 @@ tar_set_file_perms(TAR *t, char *realnam
        uid_t uid;
        gid_t gid;
        struct utimbuf ut;
-       char *filename;
+       char *filename,*pathname;
 
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        mode = th_get_mode(t);
        uid = th_get_uid(t);
        gid = th_get_gid(t);
@@ -68,6 +70,7 @@ tar_set_file_perms(TAR *t, char *realnam
                                filename, uid, gid, strerror(errno));
 # endif
 #endif /* HAVE_LCHOWN */
+                       free(pathname);
                        return -1;
                }
 
@@ -77,6 +80,7 @@ tar_set_file_perms(TAR *t, char *realnam
 #ifdef DEBUG
                perror("utime()");
 #endif
+               free(pathname);
                return -1;
        }
 
@@ -86,9 +90,10 @@ tar_set_file_perms(TAR *t, char *realnam
 #ifdef DEBUG
                perror("chmod()");
 #endif
+               free(pathname);
                return -1;
        }
-
+       free(pathname);
        return 0;
 }
 
@@ -99,6 +104,7 @@ tar_extract_file(TAR *t, char *realname)
 {
        int i;
        linkname_t *lnp;
+       char *pathname;
 
        if (t->options & TAR_NOOVERWRITE)
        {
@@ -140,12 +146,14 @@ tar_extract_file(TAR *t, char *realname)
        lnp = (linkname_t *)calloc(1, sizeof(linkname_t));
        if (lnp == NULL)
                return -1;
-       strlcpy(lnp->ln_save, th_get_pathname(t), sizeof(lnp->ln_save));
+       pathname = th_get_pathname(t);
+       strlcpy(lnp->ln_save, pathname, sizeof(lnp->ln_save));
        strlcpy(lnp->ln_real, realname, sizeof(lnp->ln_real));
 #ifdef DEBUG
        printf("tar_extract_file(): calling libtar_hash_add(): key=\"%s\", "
-              "value=\"%s\"\n", th_get_pathname(t), realname);
+              "value=\"%s\"\n", pathname, realname);
 #endif
+       free(pathname);
        if (libtar_hash_add(t->h, lnp) != 0)
                return -1;
 
@@ -164,7 +172,7 @@ tar_extract_regfile(TAR *t, char *realna
        int fdout;
        int i, k;
        char buf[T_BLOCKSIZE];
-       char *filename;
+       char *filename,*pathname;
 
 #ifdef DEBUG
        printf("==> tar_extract_regfile(t=0x%lx, realname=\"%s\")\n", t,
@@ -176,15 +184,18 @@ tar_extract_regfile(TAR *t, char *realna
                errno = EINVAL;
                return -1;
        }
-
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        mode = th_get_mode(t);
        size = th_get_size(t);
        uid = th_get_uid(t);
        gid = th_get_gid(t);
 
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("  ==> extracting: %s (mode %04o, uid %d, gid %d, %d bytes)\n",
@@ -200,6 +211,7 @@ tar_extract_regfile(TAR *t, char *realna
 #ifdef DEBUG
                perror("open()");
 #endif
+               free(pathname);
                return -1;
        }
 
@@ -231,23 +243,30 @@ tar_extract_regfile(TAR *t, char *realna
                {
                        if (k != -1)
                                errno = EINVAL;
+                       free(pathname);
                        return -1;
                }
 
                /* write block to output file */
                if (write(fdout, buf,
                          ((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1)
+               {
+                       free(pathname);
                        return -1;
+               }
        }
 
        /* close output file */
        if (close(fdout) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("### done extracting %s\n", filename);
 #endif
-
+       free(pathname);
        return 0;
 }
 
@@ -286,7 +305,7 @@ tar_skip_regfile(TAR *t)
 int
 tar_extract_hardlink(TAR * t, char *realname)
 {
-       char *filename;
+       char *filename,*pathname;
        char *linktgt = NULL;
        linkname_t *lnp;
        libtar_hashptr_t hp;
@@ -296,10 +315,14 @@ tar_extract_hardlink(TAR * t, char *real
                errno = EINVAL;
                return -1;
        }
-
-       filename = (realname ? realname : th_get_pathname(t));
+      
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
        libtar_hashptr_reset(&hp);
        if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
                               (libtar_matchfunc_t)libtar_str_match) != 0)
@@ -318,9 +341,10 @@ tar_extract_hardlink(TAR * t, char *real
 #ifdef DEBUG
                perror("link()");
 #endif
+               free(pathname);
                return -1;
        }
-
+       free(pathname);
        return 0;
 }
 
@@ -329,7 +353,7 @@ tar_extract_hardlink(TAR * t, char *real
 int
 tar_extract_symlink(TAR *t, char *realname)
 {
-       char *filename;
+       char *filename,*pathname;
 
        if (!TH_ISSYM(t))
        {
@@ -337,12 +361,19 @@ tar_extract_symlink(TAR *t, char *realna
                return -1;
        }
 
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
        if (unlink(filename) == -1 && errno != ENOENT)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("  ==> extracting: %s (symlink to %s)\n",
@@ -353,9 +384,10 @@ tar_extract_symlink(TAR *t, char *realna
 #ifdef DEBUG
                perror("symlink()");
 #endif
+               free(pathname);
                return -1;
        }
-
+       free(pathname);
        return 0;
 }
 
@@ -366,7 +398,7 @@ tar_extract_chardev(TAR *t, char *realna
 {
        mode_t mode;
        unsigned long devmaj, devmin;
-       char *filename;
+       char *filename,*pathname;
 
        if (!TH_ISCHR(t))
        {
@@ -374,13 +406,17 @@ tar_extract_chardev(TAR *t, char *realna
                return -1;
        }
 
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        mode = th_get_mode(t);
        devmaj = th_get_devmajor(t);
        devmin = th_get_devminor(t);
 
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("  ==> extracting: %s (character device %ld,%ld)\n",
@@ -392,9 +428,10 @@ tar_extract_chardev(TAR *t, char *realna
 #ifdef DEBUG
                perror("mknod()");
 #endif
+               free(pathname);
                return -1;
        }
-
+       free(pathname);
        return 0;
 }
 
@@ -405,7 +442,7 @@ tar_extract_blockdev(TAR *t, char *realn
 {
        mode_t mode;
        unsigned long devmaj, devmin;
-       char *filename;
+       char *filename,*pathname;
 
        if (!TH_ISBLK(t))
        {
@@ -413,13 +450,17 @@ tar_extract_blockdev(TAR *t, char *realn
                return -1;
        }
 
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        mode = th_get_mode(t);
        devmaj = th_get_devmajor(t);
        devmin = th_get_devminor(t);
 
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("  ==> extracting: %s (block device %ld,%ld)\n",
@@ -431,9 +472,10 @@ tar_extract_blockdev(TAR *t, char *realn
 #ifdef DEBUG
                perror("mknod()");
 #endif
+               free(pathname);
                return -1;
        }
-
+       free(pathname);
        return 0;
 }
 
@@ -443,7 +485,7 @@ int
 tar_extract_dir(TAR *t, char *realname)
 {
        mode_t mode;
-       char *filename;
+       char *filename,*pathname;
 
        if (!TH_ISDIR(t))
        {
@@ -451,11 +493,15 @@ tar_extract_dir(TAR *t, char *realname)
                return -1;
        }
 
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        mode = th_get_mode(t);
 
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("  ==> extracting: %s (mode %04o, directory)\n", filename,
@@ -470,6 +516,7 @@ tar_extract_dir(TAR *t, char *realname)
 #ifdef DEBUG
                                perror("chmod()");
 #endif
+                               free(pathname);
                                return -1;
                        }
                        else
@@ -477,6 +524,7 @@ tar_extract_dir(TAR *t, char *realname)
 #ifdef DEBUG
                                puts("  *** using existing directory");
 #endif
+                               free(pathname);
                                return 1;
                        }
                }
@@ -485,10 +533,11 @@ tar_extract_dir(TAR *t, char *realname)
 #ifdef DEBUG
                        perror("mkdir()");
 #endif
+                       free(pathname);
                        return -1;
                }
        }
-
+       free(pathname);
        return 0;
 }
 
@@ -498,7 +547,7 @@ int
 tar_extract_fifo(TAR *t, char *realname)
 {
        mode_t mode;
-       char *filename;
+       char *filename,*pathname;
 
        if (!TH_ISFIFO(t))
        {
@@ -506,11 +555,15 @@ tar_extract_fifo(TAR *t, char *realname)
                return -1;
        }
 
-       filename = (realname ? realname : th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       filename = (realname ? realname : pathname);
        mode = th_get_mode(t);
 
        if (mkdirhier(dirname(filename)) == -1)
+       {
+               free(pathname);
                return -1;
+       }
 
 #ifdef DEBUG
        printf("  ==> extracting: %s (fifo)\n", filename);
@@ -520,9 +573,11 @@ tar_extract_fifo(TAR *t, char *realname)
 #ifdef DEBUG
                perror("mkfifo()");
 #endif
+               free(pathname);
                return -1;
        }
 
+       free(pathname);
        return 0;
 }
 
--- a/lib/output.c
+++ b/lib/output.c
@@ -20,6 +20,7 @@
 #include <sys/param.h>
 
 #ifdef STDC_HEADERS
+# include <stdlib.h>
 # include <string.h>
 #endif
 
@@ -71,6 +72,7 @@ th_print_long_ls(TAR *t)
        char groupname[_POSIX_LOGIN_NAME_MAX];
        time_t mtime;
        struct tm *mtm;
+       char *pathname;
 
 #ifdef HAVE_STRFTIME
        char timebuf[18];
@@ -114,7 +116,9 @@ th_print_long_ls(TAR *t)
               mtm->tm_mday, mtm->tm_hour, mtm->tm_min, mtm->tm_year + 1900);
 #endif
 
-       printf(" %s", th_get_pathname(t));
+       pathname = th_get_pathname(t);
+       printf(" %s", pathname);
+       free(pathname);
 
        if (TH_ISSYM(t) || TH_ISLNK(t))
        {
--- a/lib/decode.c
+++ b/lib/decode.c
@@ -29,7 +29,7 @@ th_get_pathname(TAR *t)
        char filename[MAXPATHLEN];
 
        if (t->th_buf.gnu_longname)
-               return t->th_buf.gnu_longname;
+               return strdup(t->th_buf.gnu_longname);
 
        if (t->th_buf.prefix[0] != '\0')
        {