with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
-#include "config.h"
+#include <config.h>
-#include "bashtypes.h"
+#include <bashtypes.h>
#ifndef _MINIX
# include <sys/param.h>
#endif
-#include "posixstat.h"
+#include <posixstat.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
-#include "filecntl.h"
-#include "bashansi.h"
+#include <filecntl.h>
+#include <bashansi.h>
#include <stdio.h>
+#include <chartypes.h>
#include <errno.h>
#include "shell.h"
-#include "maxpath.h"
-
#if !defined (MAXSYMLINKS)
# define MAXSYMLINKS 32
#endif
/*
* Return PATH with all symlinks expanded in newly-allocated memory.
- * This always gets a full pathname.
+ * This always gets an absolute pathname.
*/
char *
char *result, *p, *q, *qsave, *qbase, *workpath;
int double_slash_path, linklen, nlink;
+ linklen = strlen (path);
+
+#if 0
+ /* First sanity check -- punt immediately if the name is too long. */
+ if (linklen >= PATH_MAX)
+ return (savestring (path));
+#endif
+
nlink = 0;
- q = result = xmalloc (PATH_MAX + 1);
+ q = result = (char *)xmalloc (PATH_MAX + 1);
- workpath = xmalloc (PATH_MAX + 1);
- strcpy (workpath, path);
+ /* Even if we get something longer than PATH_MAX, we might be able to
+ shorten it, so we try. */
+ if (linklen >= PATH_MAX)
+ workpath = savestring (path);
+ else
+ {
+ workpath = (char *)xmalloc (PATH_MAX + 1);
+ strcpy (workpath, path);
+ }
/* This always gets an absolute pathname. */
/* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any
leading `x:' (dos drive name). */
#if defined (__CYGWIN__)
- qbase = (isalpha(workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
+ qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
#else
qbase = workpath + 1;
#endif
if (q != qbase)
*q++ = DIRSEP;
while (*p && (ISDIRSEP(*p) == 0))
- *q++ = *p++;
+ {
+ if (q - result >= PATH_MAX)
+ {
+#ifdef ENAMETOOLONG
+ errno = ENAMETOOLONG;
+#else
+ errno = EINVAL;
+#endif
+ goto error;
+ }
+
+ *q++ = *p++;
+ }
*q = '\0';
{
#ifdef ELOOP
errno = ELOOP;
+#else
+ errno = EINVAL;
#endif
error:
free (result);
linkbuf[linklen] = '\0';
+ /* If the new path length would overrun PATH_MAX, punt now. */
+ if ((strlen (p) + linklen + 2) >= PATH_MAX)
+ {
+#ifdef ENAMETOOLONG
+ errno = ENAMETOOLONG;
+#else
+ errno = EINVAL;
+#endif
+ goto error;
+ }
+
/* Form the new pathname by copying the link value to a temporary
buffer and appending the rest of `workpath'. Reset p to point
to the start of the rest of the path. If the link value is an
q = result;
/* Duplicating some code here... */
#if defined (__CYGWIN__)
- qbase = (isalpha(workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
+ qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
#else
qbase = workpath + 1;
#endif
{
strncpy (resolved, wd, PATH_MAX - 1);
resolved[PATH_MAX - 1] = '\0';
+ free (wd);
return resolved;
}
else