unsafe_symlink change (Re: CVS update: rsync)

Wayne Davison wayned at users.sourceforge.net
Fri Jan 17 07:22:00 EST 2003


On Thu, Jan 16, 2003 at 08:25:32PM -0600, Dave Dykstra wrote:
> It doesn't look to me like your new code looks at the last
> component of the path like the old one might have.

Right.  I thought to myself as I was re-writing the function that that
wouldn't be possible (to end with ".."), but I could be wrong.  We might
as well handle that possibility.

> I don't expect that the strdups are of significant overhead, but as long
> as you've gone through the trouble to rewrite it I suppose we might as
> well use it (assuming you have handled the last component ok).

Since it's so close to a release we might want to delay committing this
until afterwards.  However, it is a pretty simple change, so feel free
to use it if you feel the risk is justified.  I've attached a new
version of the patch.

..wayne..
-------------- next part --------------
Index: util.c
--- util.c	15 Jan 2003 17:49:44 -0000	1.118
+++ util.c	17 Jan 2003 06:29:25 -0000
@@ -793,49 +793,42 @@
  *
  * @sa t_unsafe.c
  **/
-int unsafe_symlink(const char *dest_path, const char *src_path)
+int unsafe_symlink(const char *dest, const char *src)
 {
-	char *tok, *src, *dest;
+	const char *name, *slash;
 	int depth = 0;
 
 	/* all absolute and null symlinks are unsafe */
-	if (!dest_path || !*dest_path || *dest_path == '/') return 1;
-
-	src = strdup(src_path);
-	if (!src) out_of_memory("unsafe_symlink");
+	if (!dest || !*dest || *dest == '/') return 1;
 
 	/* find out what our safety margin is */
-	for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
-		if (strcmp(tok,"..") == 0) {
+	for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
+		if (strncmp(name, "../", 3) == 0) {
 			depth=0;
-		} else if (strcmp(tok,".") == 0) {
+		} else if (strncmp(name, "./", 2) == 0) {
 			/* nothing */
 		} else {
 			depth++;
 		}
 	}
-	free(src);
-
-	/* drop by one to account for the filename portion */
-	depth--;
-
-	dest = strdup(dest_path);
-	if (!dest) out_of_memory("unsafe_symlink");
+	if (strcmp(name, "..") == 0)
+		depth = 0;
 
-	for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
-		if (strcmp(tok,"..") == 0) {
-			depth--;
-		} else if (strcmp(tok,".") == 0) {
+	for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
+		if (strncmp(name, "../", 3) == 0) {
+			/* if at any point we go outside the current directory
+			   then stop - it is unsafe */
+			if (--depth < 0)
+				return 1;
+		} else if (strncmp(name, "./", 2) == 0) {
 			/* nothing */
 		} else {
 			depth++;
 		}
-		/* if at any point we go outside the current directory then
-		   stop - it is unsafe */
-		if (depth < 0) break;
 	}
+	if (strcmp(name, "..") == 0)
+		depth--;
 
-	free(dest);
 	return (depth < 0);
 }
 


More information about the rsync mailing list