diff mbox

Fix make_relative_prefix_1 (PR driver/48306)

Message ID 20111221144313.GZ1957@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 21, 2011, 2:43 p.m. UTC
Hi!

As reported in the PR, when the gcc (or g++, ...) binary
is not started with full path and somewhere in $PATH earlier
then were gcc binary is is a directory with the same name (gcc, g++, ...),
then execvp will ignore it, but make_relative_prefix will think it
is the path to the driver and derive paths from that, thus likely won't be
able to find cc1 etc.

The following patch fixes it by skipping pathnames that aren't regular
files.  Unfortunately it adds an extra syscall for each path element
successfully statted.  For Linux we could perhaps do better, if
we
#ifdef __linux__
  ssize_t len = readlink ("/proc/self/exe", buf, sizeof buf);
  if (len > 0 && len < sizeof buf)
    {
      buf[len] = '\0';
      /* Executable filename is in buf, goto somewhere and
	 skip the $PATH loop.  */
    }
#endif
but would need to do some portability hacks for that.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-12-21  Jakub Jelinek  <jakub@redhat.com>

	* make-relative-prefix.c (make_relative_prefix_1): Avoid
	stack overflow if PATH contains just a single entry and
	HOST_EXECUTABLE_SUFFIX needs to be used.

	PR driver/48306
	* make-relative-prefix.c: Include sys/stat.h.
	(make_relative_prefix_1): If access succeeds, check also stat
	if nstore is a regular file.


	Jakub

Comments

Ian Lance Taylor Jan. 2, 2012, 6:16 p.m. UTC | #1
On Wed, Dec 21, 2011 at 6:43 AM, Jakub Jelinek <jakub@redhat.com> wrote:

> 2011-12-21  Jakub Jelinek  <jakub@redhat.com>
>
>        * make-relative-prefix.c (make_relative_prefix_1): Avoid
>        stack overflow if PATH contains just a single entry and
>        HOST_EXECUTABLE_SUFFIX needs to be used.
>
>        PR driver/48306
>        * make-relative-prefix.c: Include sys/stat.h.
>        (make_relative_prefix_1): If access succeeds, check also stat
>        if nstore is a regular file.

This is OK.

Thanks.

Ian
diff mbox

Patch

--- libiberty/make-relative-prefix.c.jj	2011-02-15 15:40:07.000000000 +0100
+++ libiberty/make-relative-prefix.c	2011-12-19 20:47:02.613081452 +0100
@@ -1,6 +1,6 @@ 
 /* Relative (relocatable) prefix support.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2006, 2011 Free Software Foundation, Inc.
 
 This file is part of libiberty.
 
@@ -58,6 +58,9 @@  relative prefix can be found, return @co
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
 
 #include <string.h>
 
@@ -248,7 +251,11 @@  make_relative_prefix_1 (const char *prog
 	  if (prefixlen < 2)
 	    prefixlen = 2;
 
-	  nstore = (char *) alloca (prefixlen + strlen (progname) + 1);
+	  nstore = (char *) alloca (prefixlen + strlen (progname) + 1
+#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+				    + strlen (HOST_EXECUTABLE_SUFFIX)
+#endif
+				    );
 
 	  startp = endp = temp;
 	  while (1)
@@ -263,7 +270,7 @@  make_relative_prefix_1 (const char *prog
 		    }
 		  else
 		    {
-		      strncpy (nstore, startp, endp - startp);
+		      memcpy (nstore, startp, endp - startp);
 		      if (! IS_DIR_SEPARATOR (endp[-1]))
 			{
 			  nstore[endp - startp] = DIR_SEPARATOR;
@@ -279,8 +286,14 @@  make_relative_prefix_1 (const char *prog
 #endif
 		      )
 		    {
-		      progname = nstore;
-		      break;
+#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
+		      struct stat st;
+		      if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
+#endif
+			{
+			  progname = nstore;
+			  break;
+			}
 		    }
 
 		  if (*endp == 0)