[PATCH] avoid assuming MAXPATHLEN in config(8)

Robert Millan rmh at debian.org
Thu Jul 7 09:33:54 UTC 2011


config(8) assumes MAXPATHLEN is defined in a few places, but presence
of this macro isn't garanteed (POSIX says that it is only present when
a file length limit exists, which may not be the case).

This patch fixes a usr.sbin/config compile problem on Debian GNU/Hurd
by using dynamic allocation.  Doing so also reduces its memory
footprint and safeguards against possible error conditions when
zero-length pathnames are used.

-- 
Robert Millan
-------------- next part --------------
Index: usr.sbin/config/mkoptions.c
===================================================================
--- usr.sbin/config/mkoptions.c	(revision 223792)
+++ usr.sbin/config/mkoptions.c	(working copy)
@@ -290,22 +290,21 @@
 static char *
 tooption(char *name)
 {
-	static char hbuf[MAXPATHLEN];
-	char nbuf[MAXPATHLEN];
+	char *nbuf;
 	struct opt_list *po;
 
 	/* "cannot happen"?  the otab list should be complete.. */
-	(void)strlcpy(nbuf, "options.h", sizeof(nbuf));
+	nbuf = strdup("options.h");
 
 	SLIST_FOREACH(po, &otab, o_next) {
 		if (eq(po->o_name, name)) {
-			strlcpy(nbuf, po->o_file, sizeof(nbuf));
+			free(nbuf);
+			nbuf = strdup(po->o_file);
 			break;
 		}
 	}
 
-	(void)strlcpy(hbuf, path(nbuf), sizeof(hbuf));
-	return (hbuf);
+	return (nbuf);
 }
 
 	
@@ -363,7 +362,7 @@
 {
 	FILE *fp;
 	char *wd, *this, *val;
-	char genopt[MAXPATHLEN];
+	char *genopt = NULL;
 
 	fp = fopen(fname, "r");
 	if (fp == 0)
@@ -387,7 +386,7 @@
 				exit(1);
 			}
 			char *s = ns(this);
-			(void)snprintf(genopt, sizeof(genopt), "opt_%s.h",
+			(void)asprintf(&genopt, "opt_%s.h",
 			    lower(s));
 			val = genopt;
 			free(s);
@@ -399,6 +398,7 @@
 			update_option(this, val, flags);
 	}
 	(void)fclose(fp);
+	free(genopt);
 	return (1);
 }
 
@@ -408,16 +408,17 @@
 static void
 read_options(void)
 {
-	char fname[MAXPATHLEN];
+	char *fname = NULL;
 
 	SLIST_INIT(&otab);
 	read_option_file("../../conf/options", 0);
-	(void)snprintf(fname, sizeof fname, "../../conf/options.%s",
+	(void)asprintf(&fname, "../../conf/options.%s",
 	    machinename);
 	if (!read_option_file(fname, 0)) {
-		(void)snprintf(fname, sizeof fname, "options.%s", machinename);
+		(void)asprintf(&fname, "options.%s", machinename);
 		read_option_file(fname, 0);
 	}
+	free(fname);
 	read_option_file("../../conf/options-compat", OL_ALIAS);
 }
 
Index: usr.sbin/config/main.c
===================================================================
--- usr.sbin/config/main.c	(revision 223792)
+++ usr.sbin/config/main.c	(working copy)
@@ -71,8 +71,8 @@
 #define	CDIR	"../compile/"
 
 char *	PREFIX;
-char 	destdir[MAXPATHLEN];
-char 	srcdir[MAXPATHLEN];
+char *	destdir;
+char *	srcdir;
 
 int	debugging;
 int	profiling;
@@ -122,8 +122,8 @@
 			printmachine = 1;
 			break;
 		case 'd':
-			if (*destdir == '\0')
-				strlcpy(destdir, optarg, sizeof(destdir));
+			if (destdir == NULL)
+				destdir = strdup(optarg);
 			else
 				errx(EXIT_FAILURE, "directory already set");
 			break;
@@ -165,14 +165,13 @@
 			err(2, "%s", PREFIX);
 		yyfile = PREFIX;
 	}
-	if (*destdir != '\0') {
+	if (destdir != NULL) {
 		len = strlen(destdir);
 		while (len > 1 && destdir[len - 1] == '/')
 			destdir[--len] = '\0';
 		get_srcdir();
 	} else {
-		strlcpy(destdir, CDIR, sizeof(destdir));
-		strlcat(destdir, PREFIX, sizeof(destdir));
+		(void) asprintf(&destdir, CDIR "%s", PREFIX);
 	}
 
 	SLIST_INIT(&cputype);
@@ -229,6 +228,19 @@
 	exit(0);
 }
 
+#ifndef __GLIBC__
+static char *
+canonicalize_file_name(const char *pathname)
+{
+	char *ret = malloc(MAXPATHLEN);
+	if (realpath(pathname, ret) == NULL) {
+		free(ret);
+		ret = NULL;
+	}
+	return ret;
+}
+#endif
+
 /*
  * get_srcdir
  *	determine the root of the kernel source tree
@@ -241,7 +253,9 @@
 	char *p, *pwd;
 	int i;
 
-	if (realpath("../..", srcdir) == NULL)
+	if (srcdir != NULL)
+		free(srcdir);
+	if ((srcdir = canonicalize_file_name("../..")) == NULL)
 		err(EXIT_FAILURE, "Unable to find root of source tree");
 	if ((pwd = getenv("PWD")) != NULL && *pwd == '/' &&
 	    (pwd = strdup(pwd)) != NULL) {
@@ -254,9 +268,12 @@
 			*p = '\0';
 		}
 		if (stat(pwd, &lg) != -1 && stat(srcdir, &phy) != -1 &&
-		    lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino)
-			strlcpy(srcdir, pwd, MAXPATHLEN);
-		free(pwd);
+		    lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino) {
+			free(srcdir);
+			srcdir = pwd;
+		} else {
+			free(pwd);
+		}
 	}
 }
 
Index: usr.sbin/config/mkmakefile.c
===================================================================
--- usr.sbin/config/mkmakefile.c	(revision 223792)
+++ usr.sbin/config/mkmakefile.c	(working copy)
@@ -304,9 +304,9 @@
 }
 
 static void
-read_file(char *fname)
+read_file(const char *fname)
 {
-	char ifname[MAXPATHLEN];
+	char *ifname = NULL;
 	FILE *fp;
 	struct file_list *tp;
 	struct device *dp;
@@ -349,8 +349,9 @@
 			    fname);
 			exit(1);
 		}
-		(void) snprintf(ifname, sizeof(ifname), "../../%s", wd);
+		(void) asprintf(&ifname, "../../%s", wd);
 		read_file(ifname);
+		free(ifname);
 		while (((wd = get_word(fp)) != (char *)EOF) && wd)
 			;
 		goto next;
@@ -559,14 +560,13 @@
 static void
 read_files(void)
 {
-	char fname[MAXPATHLEN];
+	char *fname = NULL;
 	struct files_name *nl, *tnl;
 	
-	(void) snprintf(fname, sizeof(fname), "../../conf/files");
+	read_file("../../conf/files");
+	(void) asprintf(&fname, "../../conf/files.%s", machinename);
 	read_file(fname);
-	(void) snprintf(fname, sizeof(fname),
-		       	"../../conf/files.%s", machinename);
-	read_file(fname);
+	free(fname);
 	for (nl = STAILQ_FIRST(&fntab); nl != NULL; nl = tnl) {
 		read_file(nl->f_name);
 		tnl = STAILQ_NEXT(nl, f_next);
Index: usr.sbin/config/config.h
===================================================================
--- usr.sbin/config/config.h	(revision 223792)
+++ usr.sbin/config/config.h	(working copy)
@@ -199,7 +199,7 @@
 extern int	maxusers;
 
 extern char *PREFIX;		/* Config file name - for error messages */
-extern char srcdir[];		/* root of the kernel source tree */
+extern char *srcdir;		/* root of the kernel source tree */
 
 #define eq(a,b)	(!strcmp(a,b))
 #define ns(s)	strdup(s)


More information about the freebsd-hackers mailing list