This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: cpplib: Be safe in presence of symlinks
- To: gcc-patches at gcc dot gnu dot org
- Subject: Re: cpplib: Be safe in presence of symlinks
- From: Neil Booth <neil at daikokuya dot demon dot co dot uk>
- Date: Sat, 31 Mar 2001 22:35:16 +0100
- Cc: Zack Weinberg <zackw at Stanford dot EDU>,John David Anglin <dave at hiauly1 dot hia dot nrc dot ca>
- References: <20010331213102.A20319@daikokuya.demon.co.uk>
Sorry, there was a bug in the patch. This fixes it.
Neil.
Index: cppfiles.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppfiles.c,v
retrieving revision 1.114
diff -u -p -c -r1.114 cppfiles.c
*** cppfiles.c 2001/03/16 05:19:46 1.114
--- cppfiles.c 2001/03/31 21:34:07
*************** static int report_missing_guard PARAMS
*** 101,106 ****
--- 101,107 ----
static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *,
const char *));
static void handle_missing_header PARAMS ((cpp_reader *, const char *, int));
+ static int remove_component_p PARAMS ((const char *));
/* Set up the splay tree we use to store information about all the
file names seen in this compilation. We also have entries for each
*************** remap_filename (pfile, name, loc)
*** 1002,1007 ****
--- 1003,1023 ----
return name;
}
+ /* Returns true if it is safe to remove the final component of path,
+ when it is followed by a ".." component. */
+ static int
+ remove_component_p (path)
+ const char *path ATTRIBUTE_UNUSED;
+ {
+ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) || defined (VMS)
+ return 1;
+ #else
+ struct stat s;
+
+ return lstat (path, &s) == 0 && S_ISDIR (s.st_mode);
+ #endif
+ }
+
/* Simplify a path name in place, deleting redundant components. This
reduces OS overhead and guarantees that equivalent paths compare
the same (modulo symlinks).
*************** remap_filename (pfile, name, loc)
*** 1013,1136 ****
/../quux /quux
//quux //quux (POSIX allows leading // as a namespace escape)
! Guarantees no trailing slashes. All transforms reduce the length
! of the string. Returns PATH;
*/
char *
_cpp_simplify_pathname (path)
char *path;
{
! char *from, *to;
! char *base;
! int absolute = 0;
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
! /* Convert all backslashes to slashes. */
! for (from = path; *from; from++)
! if (*from == '\\') *from = '/';
! /* Skip over leading drive letter if present. */
! if (ISALPHA (path[0]) && path[1] == ':')
! from = to = &path[2];
! else
! from = to = path;
! #else
from = to = path;
#endif
! /* Remove redundant initial /s. */
! if (*from == '/')
{
! absolute = 1;
! to++;
! from++;
! if (*from == '/')
{
! if (*++from == '/')
! /* 3 or more initial /s are equivalent to 1 /. */
! while (*++from == '/');
! else
! /* On some hosts // differs from /; Posix allows this. */
! to++;
}
}
! base = to;
!
! for (;;)
{
! while (*from == '/')
! from++;
! if (from[0] == '.' && from[1] == '/')
! from += 2;
! else if (from[0] == '.' && from[1] == '\0')
! goto done;
! else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
{
! if (base == to)
{
! if (absolute)
! from += 3;
! else
! {
! *to++ = *from++;
! *to++ = *from++;
! *to++ = *from++;
! base = to;
! }
}
! else
{
! to -= 2;
! while (to > base && *to != '/') to--;
! if (*to == '/')
! to++;
! from += 3;
! }
! }
! else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
! {
! if (base == to)
! {
! if (!absolute)
{
! *to++ = *from++;
! *to++ = *from++;
}
! }
! else
! {
! to -= 2;
! while (to > base && *to != '/') to--;
! if (*to == '/')
! to++;
! }
! goto done;
! }
! else
! /* Copy this component and trailing /, if any. */
! while ((*to++ = *from++) != '/')
! {
! if (!to[-1])
{
! to--;
! goto done;
}
}
!
}
! done:
! /* Trim trailing slash */
! if (to[0] == '/' && (!absolute || to > path+1))
! to--;
!
! /* Change the empty string to "." so that stat() on the result
! will always work. */
! if (to == path)
! *to++ = '.';
!
! *to = '\0';
! return path;
}
--- 1029,1144 ----
/../quux /quux
//quux //quux (POSIX allows leading // as a namespace escape)
! Guarantees no trailing slashes. All transforms reduce the length
! of the string. Returns PATH.
*/
+
char *
_cpp_simplify_pathname (path)
char *path;
{
! #ifndef VMS
! char *from, *to;
! char *base, *orig_base;
! int absolute = 0;
+ /* Don't overflow the empty path by putting a '.' in it below. */
+ if (*path == '\0')
+ return path;
+
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
! /* Convert all backslashes to slashes. */
! for (from = path; *from; from++)
! if (*from == '\\') *from = '/';
! /* Skip over leading drive letter if present. */
! if (ISALPHA (path[0]) && path[1] == ':')
! from = to = &path[2];
! else
from = to = path;
+ #else
+ from = to = path;
#endif
! /* Remove redundant leading /s. */
! if (*from == '/')
{
! absolute = 1;
! to++;
! from++;
! if (*from == '/')
{
! if (*++from == '/')
! /* 3 or more initial /s are equivalent to 1 /. */
! while (*++from == '/');
! else
! /* On some hosts // differs from /; Posix allows this. */
! to++;
}
}
!
! base = orig_base = to;
! for (;;)
{
! int move_base = 0;
! while (*from == '/')
! from++;
!
! if (*from == '\0')
! break;
!
! if (*from == '.')
{
! if (from[1] == '\0')
! break;
! if (from[1] == '/')
{
! from += 2;
! continue;
}
! else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0'))
{
! if (absolute && orig_base == to)
{
! from += 2; /* Don't go past the NUL. */
! continue;
}
! /* Base is the most recent "..", to prevent simplifying it. */
! if (base != to)
{
! /* We don't back up if it's a symlink (or ..). */
! *to = '\0';
! if (remove_component_p (path))
! {
! while (to > base && *to != '/')
! to--;
! from += 2; /* Don't go past the NUL. */
! continue;
! }
}
+ move_base = 1;
}
! }
!
! /* Add the component separator. */
! if (to > orig_base)
! *to++ = '/';
!
! /* Copy this component until the trailing null or '/'. */
! while (*from != '\0' && *from != '/')
! *to++ = *from++;
!
! if (move_base)
! base = to;
}
! /* Change the empty string to "." so that it is not treated as stdin.
! Null terminate. */
! if (to == path)
! *to++ = '.';
! *to = '\0';
! #endif /* !VMS */
! return path;
}
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.245
diff -u -p -c -r1.245 cpplib.c
*** cpplib.c 2001/03/27 15:31:45 1.245
--- cpplib.c 2001/03/31 21:34:10
*************** do_line (pfile)
*** 729,740 ****
cpp_get_token (pfile, &token);
if (token.type == CPP_STRING)
{
! char *fname;
! unsigned int len = token.val.str.len + 1;
!
! fname = (char *) _cpp_pool_alloc (&pfile->ident_pool, len);
! memcpy (fname, token.val.str.text, len);
! _cpp_simplify_pathname (fname);
/* Only accept flags for the # 55 form. */
if (! pfile->state.line_extension)
--- 729,735 ----
cpp_get_token (pfile, &token);
if (token.type == CPP_STRING)
{
! char *fname = token.val.str.text;
/* Only accept flags for the # 55 form. */
if (! pfile->state.line_extension)