Hi,

Currently busybox's biggest stack user (per-function)
is actually in uclibc, not busybox. It's realpath().

Proposed patch uses user-supplied buffer directly,
without intermediate on-stack copy.
This can only make a difference if user supplied
a buffer which is too small - thus user breaks API.

Failure scenario:

realpath("/link_name", user_buffer)

/link_name -> /very_long_name_which_fits_into_PATH_MAX_and_is_also_a_link ->
-> /shorter_name

If user will give e.g. 40-char user_buffer, current implementation
will work, patched one will overflow user_buffer by intermediate name.

This should not be a problem - user must supply PATH_MAX sized buffer,
and in this case patched version also works correctly.

Run tested.

ACK, anyone?
--
vda
Index: libc/stdlib/realpath.c
===================================================================
--- libc/stdlib/realpath.c	(revision 20608)
+++ libc/stdlib/realpath.c	(working copy)
@@ -43,18 +43,21 @@
 #define MAX_READLINKS 32
 
 #ifdef __STDC__
-char *realpath(const char *path, char resolved_path[])
+char *realpath(const char *path, char got_path[])
 #else
-char *realpath(path, resolved_path)
+char *realpath(path, got_path)
 const char *path;
-char resolved_path[];
+char got_path[];
 #endif
 {
 	char copy_path[PATH_MAX];
+	/* use user supplied buffer directly - reduces stack usage */
+	/* char got_path[PATH_MAX]; */
+#ifdef S_IFLNK
 	char link_path[PATH_MAX];
-	char got_path[PATH_MAX];
+#endif
+	const char *max_path;
 	char *new_path = got_path;
-	char *max_path;
 	int readlinks = 0;
 	int n;
 
@@ -124,18 +127,21 @@
 			__set_errno(ELOOP);
 			return NULL;
 		}
-		/* See if latest pathname component is a symlink. */
+		/* See if last (so far) pathname component is a symlink. */
 		*new_path = '\0';
 		n = readlink(got_path, link_path, PATH_MAX - 1);
 		if (n < 0) {
 			/* EINVAL means the file exists but isn't a symlink. */
 			if (errno != EINVAL) {
-				/* Make sure it's null terminated. */
-				*new_path = '\0';
-				strcpy(resolved_path, got_path);
+				/*strcpy(resolved_path, got_path);*/
 				return NULL;
 			}
 		} else {
+			/* Safe sex check. */
+			if (strlen(path) + n >= PATH_MAX - 2) {
+				__set_errno(ENAMETOOLONG);
+				return NULL;
+			}
 			/* Note: readlink doesn't add the null byte. */
 			link_path[n] = '\0';
 			if (*link_path == '/')
@@ -144,13 +150,8 @@
 			else
 				/* Otherwise back up over this component. */
 				while (*(--new_path) != '/');
-			/* Safe sex check. */
-			if (strlen(path) + n >= PATH_MAX - 2) {
-				__set_errno(ENAMETOOLONG);
-				return NULL;
-			}
 			/* Insert symlink contents into path. */
-			strcat(link_path, path);
+			strcpy(link_path + n, path);
 			strcpy(copy_path, link_path);
 			path = copy_path;
 		}
@@ -162,6 +163,6 @@
 		new_path--;
 	/* Make sure it's null terminated. */
 	*new_path = '\0';
-	strcpy(resolved_path, got_path);
-	return resolved_path;
+	/*strcpy(resolved_path, got_path);*/
+	return got_path;
 }
_______________________________________________
uClibc mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/uclibc

Reply via email to