This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: cpplib: Be safe in presence of symlinks


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]