--- include/stdlib.h
+++ include/stdlib.h
@@ -628,17 +628,13 @@
      __THROW __nonnull ((1)) __wur;
 #endif
 
-#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
-/* Return the canonical absolute name of file NAME.  The last file name
-   component need not exist, and may be a symlink to a nonexistent file.
-   If RESOLVED is null, the result is malloc'd; otherwise, if the canonical
-   name is PATH_MAX chars or more, returns null with `errno' set to
-   ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the
-   name in RESOLVED.  */
-/* we choose to handle __resolved==NULL as crash :) */
+/* Return the canonical absolute name of file NAME.  If RESOLVED is
+   null, the result is malloc'd; otherwise, if the canonical name is
+   PATH_MAX chars or more, returns null with `errno' set to
+   ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
+   returns the name in RESOLVED.  */
 extern char *realpath (__const char *__restrict __name,
-		       char *__restrict __resolved) __THROW __wur __nonnull((2));
-#endif
+		       char *__restrict __resolved) __THROW __wur;
 
 
 /* Shorthand for type of comparison functions.  */
--- libc/stdlib/realpath.c
+++ libc/stdlib/realpath.c
@@ -42,21 +41,15 @@
 
 #define MAX_READLINKS 32
 
-#ifdef __STDC__
-char *realpath(const char *path, char resolved_path[])
-#else
-char *realpath(path, resolved_path)
-const char *path;
-char resolved_path[];
-#endif
+char *realpath(const char *path, char got_path[])
 {
 	char copy_path[PATH_MAX];
-	char link_path[PATH_MAX];
-	char got_path[PATH_MAX];
-	char *new_path = got_path;
-	char *max_path;
+	char *max_path, *new_path, *allocated_path;
+	size_t path_len;
 	int readlinks = 0;
-	int n;
+#ifdef S_IFLNK
+	int link_len;
+#endif
 
 	if (path == NULL) {
 		__set_errno(EINVAL);
@@ -67,17 +60,21 @@
 		return NULL;
 	}
 	/* Make a copy of the source path since we may need to modify it. */
-	if (strlen(path) >= PATH_MAX - 2) {
+	path_len = strlen(path);
+	if (path_len >= PATH_MAX - 2) {
 		__set_errno(ENAMETOOLONG);
 		return NULL;
 	}
-	strcpy(copy_path, path);
-	path = copy_path;
-	max_path = copy_path + PATH_MAX - 2;
-	/* If it's a relative pathname use getcwd for starters. */
+	/* Copy so that path is at the end of copy_path[] */
+	strcpy(copy_path + (PATH_MAX-1) - path_len, path);
+	path = copy_path + (PATH_MAX-1) - path_len;
+	allocated_path = got_path ? NULL : (got_path = malloc(PATH_MAX));
+	max_path = got_path + PATH_MAX - 2; /* points to last non-NUL char */
+	new_path = got_path;
 	if (*path != '/') {
-		/* Ohoo... */
-		getcwd(new_path, PATH_MAX - 1);
+		/* If it's a relative pathname use getcwd for starters. */
+		if (!getcwd(new_path, PATH_MAX - 1))
+			goto err;
 		new_path += strlen(new_path);
 		if (new_path[-1] != '/')
 			*new_path++ = '/';
@@ -112,8 +109,10 @@
 		}
 		/* Safely copy the next pathname component. */
 		while (*path != '\0' && *path != '/') {
-			if (path > max_path) {
+			if (new_path > max_path) {
 				__set_errno(ENAMETOOLONG);
+ err:
+				free(allocated_path);
 				return NULL;
 			}
 			*new_path++ = *path++;
@@ -122,37 +121,38 @@
 		/* Protect against infinite loops. */
 		if (readlinks++ > MAX_READLINKS) {
 			__set_errno(ELOOP);
-			return NULL;
+			goto err;
 		}
-		/* See if latest pathname component is a symlink. */
+		path_len = strlen(path);
+		/* 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) {
+		{
+			int sv_errno = errno;
+			link_len = readlink(got_path, copy_path, PATH_MAX - 1);
+			if (link_len < 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);
-				return NULL;
+					goto err;
 			}
 		} else {
+				/* Safe sex check. */
+				if (path_len + link_len >= PATH_MAX - 2) {
+					__set_errno(ENAMETOOLONG);
+					goto err;
+				}
 			/* Note: readlink doesn't add the null byte. */
-			link_path[n] = '\0';
-			if (*link_path == '/')
+				/* copy_path[link_len] = '\0'; - we don't need it too */
+				if (*copy_path == '/')
 				/* Start over for an absolute symlink. */
 				new_path = got_path;
 			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;
+				/* Prepend symlink contents to path. */
+				memmove(copy_path + (PATH_MAX-1) - link_len - path_len, copy_path, link_len);
+				path = copy_path + (PATH_MAX-1) - link_len - path_len;
 			}
-			/* Insert symlink contents into path. */
-			strcat(link_path, path);
-			strcpy(copy_path, link_path);
-			path = copy_path;
+			__set_errno(sv_errno);
 		}
 #endif							/* S_IFLNK */
 		*new_path++ = '/';
@@ -162,6 +162,5 @@
 		new_path--;
 	/* Make sure it's null terminated. */
 	*new_path = '\0';
-	strcpy(resolved_path, got_path);
-	return resolved_path;
+	return got_path;
 }
