BUG: Fix mem leaks related to th_get_pathname. Change this implementation of th_get_pathname so that it *always* returns a strdup'ed value. Callers must now free non-NULL returns from th_get_pathname. Change all callers to call free appropriately.

This commit is contained in:
David Cole 2006-02-03 11:48:44 -05:00
parent afa8367885
commit 0323a0d6d2
4 changed files with 286 additions and 18 deletions

View File

@ -31,13 +31,15 @@
/* determine full path name */
/* caller must "free" returned pointer when done with it */
/* th_get_pathname return values come directly from strdup */
char *
th_get_pathname(TAR *t)
{
char filename[TAR_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')
{

View File

@ -61,8 +61,18 @@ tar_set_file_perms(TAR *t, char *realname)
gid_t gid;
struct utimbuf ut;
char *filename;
char *pathname = 0;
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
filename = (realname ? realname : th_get_pathname(t));
mode = th_get_mode(t);
uid = th_get_uid(t);
gid = th_get_gid(t);
@ -86,6 +96,10 @@ tar_set_file_perms(TAR *t, char *realname)
filename, uid, gid, strerror(errno));
# endif
#endif /* HAVE_LCHOWN */
if (pathname)
{
free(pathname);
}
return -1;
}
@ -95,6 +109,10 @@ tar_set_file_perms(TAR *t, char *realname)
#ifdef DEBUG
perror("utime()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
/* change permissions */
@ -103,6 +121,10 @@ tar_set_file_perms(TAR *t, char *realname)
#ifdef DEBUG
perror("chmod()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
@ -113,6 +135,10 @@ tar_set_file_perms(TAR *t, char *realname)
(void)mode;
#endif /* WIN32 */
if (pathname)
{
free(pathname);
}
return 0;
}
@ -123,6 +149,7 @@ tar_extract_file(TAR *t, char *realname)
{
int i;
linkname_t *lnp;
char *pathname = 0;
if (t->options & TAR_NOOVERWRITE)
{
@ -170,12 +197,17 @@ 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
if (pathname)
{
free(pathname);
}
if (libtar_hash_add(t->h, lnp) != 0)
return -1;
@ -195,6 +227,7 @@ tar_extract_regfile(TAR *t, char *realname)
int i, k;
char buf[T_BLOCKSIZE];
char *filename;
char *pathname = 0;
#ifdef DEBUG
printf("==> tar_extract_regfile(t=0x%lx, realname=\"%s\")\n", t,
@ -207,7 +240,15 @@ tar_extract_regfile(TAR *t, char *realname)
return -1;
}
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
mode = th_get_mode(t);
size = th_get_size(t);
uid = th_get_uid(t);
@ -220,6 +261,10 @@ tar_extract_regfile(TAR *t, char *realname)
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
@ -237,6 +282,10 @@ tar_extract_regfile(TAR *t, char *realname)
#ifdef DEBUG
perror("open()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
@ -247,6 +296,10 @@ tar_extract_regfile(TAR *t, char *realname)
#ifdef DEBUG
perror("fchown()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
@ -256,6 +309,10 @@ tar_extract_regfile(TAR *t, char *realname)
#ifdef DEBUG
perror("fchmod()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
#endif
@ -268,18 +325,34 @@ tar_extract_regfile(TAR *t, char *realname)
{
if (k != -1)
errno = EINVAL;
if (pathname)
{
free(pathname);
}
return -1;
}
/* write block to output file */
if (write(fdout, buf,
((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
}
/* close output file */
if (close(fdout) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
#ifdef DEBUG
printf("### done extracting %s\n", filename);
@ -290,6 +363,10 @@ tar_extract_regfile(TAR *t, char *realname)
(void)uid;
(void)mode;
if (pathname)
{
free(pathname);
}
return 0;
}
@ -333,6 +410,7 @@ tar_extract_hardlink(TAR * t, char *realname)
linkname_t *lnp;
libtar_hashptr_t hp;
char buf[T_BLOCKSIZE];
char *pathname = 0;
if (!TH_ISLNK(t))
{
@ -340,7 +418,15 @@ tar_extract_hardlink(TAR * t, char *realname)
return -1;
}
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
/* Make a copy of the string because dirname and mkdirhier may modify the
* string */
@ -348,7 +434,13 @@ tar_extract_hardlink(TAR * t, char *realname)
buf[sizeof(buf)-1] = 0;
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
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)
@ -371,9 +463,17 @@ tar_extract_hardlink(TAR * t, char *realname)
#ifdef DEBUG
perror("link()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
if (pathname)
{
free(pathname);
}
return 0;
}
@ -384,6 +484,7 @@ tar_extract_symlink(TAR *t, char *realname)
{
char *filename;
char buf[T_BLOCKSIZE];
char *pathname = 0;
#ifndef _WIN32
if (!TH_ISSYM(t))
@ -393,7 +494,15 @@ tar_extract_symlink(TAR *t, char *realname)
}
#endif
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
/* Make a copy of the string because dirname and mkdirhier may modify the
* string */
@ -401,10 +510,20 @@ tar_extract_symlink(TAR *t, char *realname)
buf[sizeof(buf)-1] = 0;
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
if (unlink(filename) == -1 && errno != ENOENT)
{
if (pathname)
{
free(pathname);
}
return -1;
}
@ -419,9 +538,17 @@ tar_extract_symlink(TAR *t, char *realname)
#ifdef DEBUG
perror("symlink()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
if (pathname)
{
free(pathname);
}
return 0;
}
@ -434,6 +561,7 @@ tar_extract_chardev(TAR *t, char *realname)
unsigned long devmaj, devmin;
char *filename;
char buf[T_BLOCKSIZE];
char *pathname = 0;
#ifndef _WIN32
if (!TH_ISCHR(t))
@ -442,7 +570,15 @@ tar_extract_chardev(TAR *t, char *realname)
return -1;
}
#endif
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
mode = th_get_mode(t);
devmaj = th_get_devmajor(t);
devmin = th_get_devminor(t);
@ -453,7 +589,13 @@ tar_extract_chardev(TAR *t, char *realname)
buf[sizeof(buf)-1] = 0;
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
#ifdef DEBUG
printf(" ==> extracting: %s (character device %ld,%ld)\n",
@ -471,9 +613,17 @@ tar_extract_chardev(TAR *t, char *realname)
#ifdef DEBUG
perror("mknod()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
if (pathname)
{
free(pathname);
}
return 0;
}
@ -486,6 +636,7 @@ tar_extract_blockdev(TAR *t, char *realname)
unsigned long devmaj, devmin;
char *filename;
char buf[T_BLOCKSIZE];
char *pathname = 0;
if (!TH_ISBLK(t))
{
@ -493,7 +644,15 @@ tar_extract_blockdev(TAR *t, char *realname)
return -1;
}
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
mode = th_get_mode(t);
devmaj = th_get_devmajor(t);
devmin = th_get_devminor(t);
@ -504,7 +663,13 @@ tar_extract_blockdev(TAR *t, char *realname)
buf[sizeof(buf)-1] = 0;
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
#ifdef DEBUG
printf(" ==> extracting: %s (block device %ld,%ld)\n",
@ -522,9 +687,17 @@ tar_extract_blockdev(TAR *t, char *realname)
#ifdef DEBUG
perror("mknod()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
if (pathname)
{
free(pathname);
}
return 0;
}
@ -536,6 +709,7 @@ tar_extract_dir(TAR *t, char *realname)
mode_t mode;
char *filename;
char buf[T_BLOCKSIZE];
char *pathname = 0;
if (!TH_ISDIR(t))
{
@ -543,7 +717,15 @@ tar_extract_dir(TAR *t, char *realname)
return -1;
}
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
mode = th_get_mode(t);
/* Make a copy of the string because dirname and mkdirhier may modify the
@ -552,7 +734,13 @@ tar_extract_dir(TAR *t, char *realname)
buf[sizeof(buf)-1] = 0;
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
#ifdef DEBUG
printf(" ==> extracting: %s (mode %04o, directory)\n", filename,
@ -581,6 +769,10 @@ tar_extract_dir(TAR *t, char *realname)
#ifdef DEBUG
perror("chmod()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
else
@ -588,6 +780,10 @@ tar_extract_dir(TAR *t, char *realname)
#ifdef DEBUG
puts(" *** using existing directory");
#endif
if (pathname)
{
free(pathname);
}
return 1;
}
}
@ -596,10 +792,18 @@ tar_extract_dir(TAR *t, char *realname)
#ifdef DEBUG
perror("mkdir()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
}
if (pathname)
{
free(pathname);
}
return 0;
}
@ -611,6 +815,7 @@ tar_extract_fifo(TAR *t, char *realname)
mode_t mode;
char *filename;
char buf[T_BLOCKSIZE];
char *pathname = 0;
if (!TH_ISFIFO(t))
{
@ -618,7 +823,15 @@ tar_extract_fifo(TAR *t, char *realname)
return -1;
}
filename = (realname ? realname : th_get_pathname(t));
if (realname)
{
filename = realname;
}
else
{
pathname = th_get_pathname(t);
filename = pathname;
}
mode = th_get_mode(t);
/* Make a copy of the string because dirname and mkdirhier may modify the
@ -627,7 +840,13 @@ tar_extract_fifo(TAR *t, char *realname)
buf[sizeof(buf)-1] = 0;
if (mkdirhier(dirname(buf)) == -1)
{
if (pathname)
{
free(pathname);
}
return -1;
}
#ifdef DEBUG
printf(" ==> extracting: %s (fifo)\n", filename);
@ -641,10 +860,16 @@ tar_extract_fifo(TAR *t, char *realname)
#ifdef DEBUG
perror("mkfifo()");
#endif
if (pathname)
{
free(pathname);
}
return -1;
}
if (pathname)
{
free(pathname);
}
return 0;
}

View File

@ -76,6 +76,7 @@ th_print_long_ls(TAR *t)
char groupname[_POSIX_LOGIN_NAME_MAX];
time_t mtime;
struct tm *mtm;
char *pathname = 0;
#ifdef HAVE_STRFTIME
char timebuf[18];
@ -124,7 +125,12 @@ 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);
if (pathname)
{
printf(" %s", pathname);
free(pathname);
}
#if !defined(_WIN32) || defined(__CYGWIN__)
if (TH_ISSYM(t) || TH_ISLNK(t))
@ -142,5 +148,3 @@ th_print_long_ls(TAR *t)
putchar('\n');
}

View File

@ -39,24 +39,49 @@ tar_extract_glob(TAR *t, char *globname, char *prefix)
char *filename;
char buf[TAR_MAXPATHLEN];
int i;
char *pathname = 0;
while ((i = th_read(t)) == 0)
{
filename = th_get_pathname(t);
pathname = th_get_pathname(t);
filename = pathname;
if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD))
{
if (pathname)
{
free(pathname);
pathname = 0;
}
if (TH_ISREG(t) && tar_skip_regfile(t))
return -1;
continue;
}
if (t->options & TAR_VERBOSE)
th_print_long_ls(t);
if (prefix != NULL)
snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
else
strlcpy(buf, filename, sizeof(buf));
if (tar_extract_file(t, filename) != 0)
{
if (pathname)
{
free(pathname);
pathname = 0;
}
return -1;
}
if (pathname)
{
free(pathname);
pathname = 0;
}
}
return (i == 1 ? 0 : -1);
@ -69,6 +94,7 @@ tar_extract_all(TAR *t, char *prefix)
char *filename;
char buf[TAR_MAXPATHLEN];
int i;
char *pathname = 0;
#ifdef DEBUG
printf("==> tar_extract_all(TAR *t, \"%s\")\n",
@ -80,17 +106,28 @@ tar_extract_all(TAR *t, char *prefix)
#ifdef DEBUG
puts(" tar_extract_all(): calling th_get_pathname()");
#endif
filename = th_get_pathname(t);
pathname = th_get_pathname(t);
filename = pathname;
if (t->options & TAR_VERBOSE)
th_print_long_ls(t);
if (prefix != NULL)
snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
else
strlcpy(buf, filename, sizeof(buf));
if (pathname)
{
free(pathname);
pathname = 0;
}
#ifdef DEBUG
printf(" tar_extract_all(): calling tar_extract_file(t, "
"\"%s\")\n", buf);
#endif
if (tar_extract_file(t, buf) != 0)
return -1;
}