söndagen den 9 februari 2014 19.35.06 skrev  Magnus Holmgren:
> fredagen den 31 januari 2014 23.01.54 skrev du:
> > I've attached an updated patch solving some of the issues upstream
> > commented on in the last patch.  I have not had time to update all of
> > it yet, but thought it best to check if it would get accepted into
> > Debian even if upstream refuse to include it.
> 
> I think you've missed a couple of free()s, at least in the various loops in
> wrapper.c. The final free()s could be moved inside the loops, but the plan
> was to reuse the already allocated buffer if it's large enough, wasn't it?
> 
> Using strlcpy after having already ascertained that the buffer is large
> enough is unnecessary (the existing code used strlcpy, it's not something
> you added, I know).

Also you seem to have messed upp savepath in tar_append_tree.

I've updated your updated patch. Any comments? Perhaps my realloc_if_needed() 
code is overly complicated. I'm guessing that free()ing buf and malloc()ing it 
again is in practice going to reuse the same memory anyway, and the overhead 
is negligible.

Since 1.2.21 isn't released yet I'm going to include the commit that did away 
with the static buffer and introduced th_pathname rather than creating an 
orig.tar.gz from the latest git commit, although that might not be a bad idea 
either.

-- 
Magnus Holmgren        [email protected]
Debian Developer 
Author: Svante Signell <[email protected]>
Author: Petter Reinholdtsen <[email protected]>
Author: Magnus Holmgren <[email protected]>
Bug-Debian: http://bugs.debian.org/657116
Description: Fix FTBFS on Hurd by dynamically allocating path names.
 Depends on no_static_buffers.patch, which introduced the th_pathname field.

--- a/compat/basename.c
+++ b/compat/basename.c
@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: basenam
 #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);
 }
--- a/compat/dirname.c
+++ b/compat/dirname.c
@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: dirname
 #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') {
--- 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 *real
 	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 *real
 	}
 	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 */
--- a/lib/decode.c
+++ b/lib/decode.c
@@ -29,10 +29,13 @@ th_get_pathname(TAR *t)
 	if (t->th_buf.gnu_longname)
 		return t->th_buf.gnu_longname;
 
+	size_t pathlen =
+	  strlen(t->th_buf.prefix) + strlen(t->th_buf.name) + 2;
+
 	/* allocate the th_pathname buffer if not already */
 	if (t->th_pathname == NULL)
 	{
-		t->th_pathname = malloc(MAXPATHLEN * sizeof(char));
+		t->th_pathname = malloc(pathlen);
 		if (t->th_pathname == NULL)
 			/* out of memory */
 			return NULL;
@@ -40,11 +43,11 @@ th_get_pathname(TAR *t)
 
 	if (t->th_buf.prefix[0] == '\0')
 	{
-		snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name);
+		snprintf(t->th_pathname, pathlen, "%.100s", t->th_buf.name);
 	}
 	else
 	{
-		snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s",
+		snprintf(t->th_pathname, pathlen, "%.155s/%.100s",
 			 t->th_buf.prefix, t->th_buf.name);
 	}
 
--- 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;
 }
 
--- a/lib/wrapper.c
+++ b/lib/wrapper.c
@@ -16,18 +16,34 @@
 #include <sys/param.h>
 #include <dirent.h>
 #include <errno.h>
+#include <stdlib.h>
 
 #ifdef STDC_HEADERS
 # include <string.h>
 #endif
 
+inline void *
+realloc_if_needed(void *buf, size_t *cursize, size_t newsize)
+{
+	void *tmp;
+	if (newsize > *cursize || !buf)
+	{
+		if ((tmp = realloc(buf, newsize)) == NULL)
+		{
+			free(buf);
+			return NULL;
+		}
+	}
+	return buf;
+}
 
 int
 tar_extract_glob(TAR *t, char *globname, char *prefix)
 {
 	char *filename;
-	char buf[MAXPATHLEN];
-	int i;
+	char *buf = NULL;
+	size_t bufsize = 0;
+	int i, len;
 
 	while ((i = th_read(t)) == 0)
 	{
@@ -41,13 +57,27 @@ tar_extract_glob(TAR *t, char *globname,
 		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 = realloc_if_needed(buf, &bufsize, len + 1)) == NULL)
+				return -1;
+			sprintf(buf, "%s/%s", prefix, filename);
+		}
 		else
-			strlcpy(buf, filename, sizeof(buf));
+		{
+			len = strlen(filename);
+			if ((buf = realloc_if_needed(buf, &bufsize, 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 +86,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",
@@ -69,21 +100,36 @@ tar_extract_all(TAR *t, char *prefix)
 #ifdef DEBUG
 		puts("    tar_extract_all(): calling th_get_pathname()");
 #endif
+
 		filename = th_get_pathname(t);
 		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 = realloc_if_needed(buf, &bufsize, len + 1)) == NULL)
+				return -1;
+			sprintf(buf, "%s/%s", prefix, filename);
+		}
 		else
-			strlcpy(buf, filename, sizeof(buf));
+		{
+			len = strlen(filename);
+			if ((buf = realloc_if_needed(buf, &bufsize, 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 +137,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 +171,19 @@ tar_append_tree(TAR *t, char *realdir, c
 		    strcmp(dent->d_name, "..") == 0)
 			continue;
 
-		snprintf(realpath, MAXPATHLEN, "%s/%s", realdir,
+		len = strlen(realdir) + 1 + strlen(dent->d_name);
+		if ((realpath = realloc_if_needed(realpath, &realpathsize, 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 = realloc_if_needed(savepath, &savepathsize, len + 1)) == NULL)
+				return -1;
+			snprintf(realpath, len + 1, "%s/%s", savedir,
 				 dent->d_name);
+		}
 
 		if (lstat(realpath, &s) != 0)
 			return -1;
@@ -135,15 +192,25 @@ tar_append_tree(TAR *t, char *realdir, c
 		{
 			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);
 
 	return 0;
--- a/libtar/libtar.c
+++ b/libtar/libtar.c
@@ -111,8 +111,9 @@ create(char *tarfile, char *rootdir, lib
 {
 	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, lib
 	{
 		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)

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to