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]
Other format: [Raw text]

[PATCH] Fix PR36968: malloc corruption in libiberty/pex-win32.c


The current code in spawn_script writes to argv[-1] when it is extending argv with the interpreter path when simulating Unix-style script execution. The attach patch fixes this by allocating a new, larger argv array first.

The heap corruption was causing bootstrap to fail; see <http://gcc.gnu.org/PR36968>.

This was tested by bootstrapping on i386-pc-mingw32.

OK to commit?
2008-07-31  Aaron W. LaFramboise  <aaronavay62@aaronwl.com>

	* pex-win32.c (argv_to_argc): New function.
	(spawn_script): Duplicate argv before calling win32_spawn.

Index: libiberty/pex-win32.c
===================================================================
--- libiberty/pex-win32.c	(revision 138440)
+++ libiberty/pex-win32.c	(working copy)
@@ -321,6 +321,18 @@ msys_rootify (const char *executable)
 }
 #endif
 
+/* Return the number of arguments in an argv array, not including the null
+   terminating argument. */
+
+static int
+argv_to_argc (char *const *argv)
+{
+  char *const *i = argv;
+  while (*i)
+    i++;
+  return i - argv;
+}
+
 /* Return a Windows command-line from ARGV.  It is the caller's
    responsibility to free the string returned.  */
 
@@ -522,6 +534,9 @@ env_compare (const void *a_ptr, const vo
   return c1 - c2;
 }
 
+/* Execute a Windows executable as a child process.  This will fail if the
+ * target is not actually an executable, such as if it is a shell script. */
+
 static pid_t
 win32_spawn (const char *executable,
 	     BOOL search,
@@ -619,6 +634,9 @@ win32_spawn (const char *executable,
   return (pid_t) -1;
 }
 
+/* Spawn a script.  This simulates the Unix script execution mechanism.
+   This function is called as a fallback if win32_spawn fails. */
+
 static pid_t
 spawn_script (const char *executable, char *const *argv,
               char* const *env,
@@ -630,6 +648,8 @@ spawn_script (const char *executable, ch
   int save_errno = errno;
   int fd = _open (executable, _O_RDONLY);
 
+  /* Try to open script, check header format, extract interpreter path,
+     and spawn script using that interpretter. */
   if (fd >= 0)
     {
       char buf[MAX_PATH + 5];
@@ -642,16 +662,28 @@ spawn_script (const char *executable, ch
 	  eol = strchr (buf, '\n');
 	  if (eol && strncmp (buf, "#!", 2) == 0)
 	    {
+            
+	      /* Header format is OK. */
 	      char *executable1;
-	      const char ** avhere = (const char **) --argv;
+              int new_argc;
+              const char **avhere;
+
+	      /* Extract interpreter path. */
 	      do
 		*eol = '\0';
 	      while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
 	      for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
 		continue;
-
 	      backslashify (executable1);
+
+	      /* Duplicate argv, prepending the interpreter path. */
+	      new_argc = argv_to_argc (argv) + 1;
+	      avhere = XNEWVEC (const char *, new_argc + 1);
 	      *avhere = executable1;
+	      memcpy (avhere + 1, argv, new_argc * sizeof(*argv));
+	      argv = (char *const *)avhere;
+
+	      /* Spawn the child. */
 #ifndef USE_MINGW_MSYS
 	      executable = strrchr (executable1, '\\') + 1;
 	      if (!executable)
@@ -686,6 +718,7 @@ spawn_script (const char *executable, ch
 		    }
 		}
 #endif
+	      free (avhere);
 	    }
 	}
     }

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