[libiberty patch] Fix PGO bootstrap
authorNathan Sidwell <nathan@acm.org>
Thu, 23 Aug 2018 10:21:21 +0000 (10:21 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 23 Aug 2018 10:21:21 +0000 (10:21 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01386.html
PR driver/87056
* pex-unix.c (pex_unix_exec_child): Duplicate bad_fn into local
scopes to avoid potential clobber.

Co-Authored-By: Martin Liska <mliska@suse.cz>
From-SVN: r263807

libiberty/ChangeLog
libiberty/pex-unix.c

index 22d995f8cfb80bccddeb8865571ca84e86e5f01c..ed07acfa73a8ffb5a3e333aee1244649e5a72dee 100644 (file)
@@ -1,3 +1,10 @@
+2018-08-23  Nathan Sidwell  <nathan@acm.org>
+           Martin Liska  <mliska@suse.cz>
+
+       PR driver/87056
+       * pex-unix.c (pex_unix_exec_child): Duplicate bad_fn into local
+       scopes to avoid potential clobber.
+
 2018-08-20  Nathan Sidwell  <nathan@acm.org>
 
        * pex-unix.c (pex_child_error): Delete.
index ea5ee4c141bbac682e0dd89e7e4ae65e1db45f22..703010bdeae873877c1f3fa123fa8c15b078ef27 100644 (file)
@@ -582,8 +582,6 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
      issues.   */
   char **save_environ = environ;
 
-  const char *bad_fn = NULL;
-
   for (retries = 0; retries < 4; ++retries)
     {
       pid = vfork ();
@@ -602,62 +600,64 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
 
     case 0:
       /* Child process.  */
-      if (!bad_fn && in != STDIN_FILE_NO)
-       {
-         if (dup2 (in, STDIN_FILE_NO) < 0)
-           bad_fn = "dup2";
-         else if (close (in) < 0)
-           bad_fn = "close";
-       }
-      if (!bad_fn && out != STDOUT_FILE_NO)
-       {
-         if (dup2 (out, STDOUT_FILE_NO) < 0)
-           bad_fn = "dup2";
-         else if (close (out) < 0)
-           bad_fn = "close";
-       }
-      if (!bad_fn && errdes != STDERR_FILE_NO)
-       {
-         if (dup2 (errdes, STDERR_FILE_NO) < 0)
-           bad_fn = "dup2";
-         else if (close (errdes) < 0)
-           bad_fn = "close";
-       }
-      if (!bad_fn && toclose >= 0)
-       {
-         if (close (toclose) < 0)
-           bad_fn = "close";
-       }
-      if (!bad_fn && (flags & PEX_STDERR_TO_STDOUT) != 0)
-       {
-         if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
-           bad_fn = "dup2";
-       }
-      if (!bad_fn)
-       {
-         if (env)
-           /* NOTE: In a standard vfork implementation this clobbers
-              the parent's copy of environ "too" (in reality there's
-              only one copy).  This is ok as we restore it below.  */
-           environ = (char**) env;
-         if ((flags & PEX_SEARCH) != 0)
-           {
-             execvp (executable, to_ptr32 (argv));
-             bad_fn = "execvp";
-           }
-         else
-           {
-             execv (executable, to_ptr32 (argv));
-             bad_fn = "execv";
-           }
-       }
-
-      /* Something failed, report an error.  We don't use stdio
-        routines, because we might be here due to a vfork call.  */
       {
+       const char *bad_fn = NULL;
+
+       if (!bad_fn && in != STDIN_FILE_NO)
+         {
+           if (dup2 (in, STDIN_FILE_NO) < 0)
+             bad_fn = "dup2";
+           else if (close (in) < 0)
+             bad_fn = "close";
+         }
+       if (!bad_fn && out != STDOUT_FILE_NO)
+         {
+           if (dup2 (out, STDOUT_FILE_NO) < 0)
+             bad_fn = "dup2";
+           else if (close (out) < 0)
+             bad_fn = "close";
+         }
+       if (!bad_fn && errdes != STDERR_FILE_NO)
+         {
+           if (dup2 (errdes, STDERR_FILE_NO) < 0)
+             bad_fn = "dup2";
+           else if (close (errdes) < 0)
+             bad_fn = "close";
+         }
+       if (!bad_fn && toclose >= 0)
+         {
+           if (close (toclose) < 0)
+             bad_fn = "close";
+         }
+       if (!bad_fn && (flags & PEX_STDERR_TO_STDOUT) != 0)
+         {
+           if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
+             bad_fn = "dup2";
+         }
+       if (!bad_fn)
+         {
+           if (env)
+             /* NOTE: In a standard vfork implementation this clobbers
+                the parent's copy of environ "too" (in reality there's
+                only one copy).  This is ok as we restore it below.  */
+             environ = (char**) env;
+           if ((flags & PEX_SEARCH) != 0)
+             {
+               execvp (executable, to_ptr32 (argv));
+               bad_fn = "execvp";
+             }
+           else
+             {
+               execv (executable, to_ptr32 (argv));
+               bad_fn = "execv";
+             }
+         }
+
+       /* Something failed, report an error.  We don't use stdio
+          routines, because we might be here due to a vfork call.  */
        ssize_t retval = 0;
-       int err = errno;
-
+       int eno = errno;
+       
 #define writeerr(s) (retval |= write (STDERR_FILE_NO, s, strlen (s)))
        writeerr (obj->pname);
        writeerr (": error trying to exec '");
@@ -665,7 +665,7 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
        writeerr ("': ");
        writeerr (bad_fn);
        writeerr (": ");
-       writeerr (xstrerror (err));
+       writeerr (xstrerror (eno));
        writeerr ("\n");
 #undef writeerr
 
@@ -677,30 +677,33 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
 
     default:
       /* Parent process.  */
+      {
+       const char *bad_fn = NULL;
+       
+       /* Restore environ.  Note that the parent either doesn't run
+          until the child execs/exits (standard vfork behaviour), or
+          if it does run then vfork is behaving more like fork.  In
+          either case we needn't worry about clobbering the child's
+          copy of environ.  */
+       environ = save_environ;
+
+       if (!bad_fn && in != STDIN_FILE_NO)
+         if (close (in) < 0)
+           bad_fn = "close";
+       if (!bad_fn && out != STDOUT_FILE_NO)
+         if (close (out) < 0)
+           bad_fn = "close";
+       if (!bad_fn && errdes != STDERR_FILE_NO)
+         if (close (errdes) < 0)
+           bad_fn = "close";
 
-      /* Restore environ.
-        Note that the parent either doesn't run until the child execs/exits
-        (standard vfork behaviour), or if it does run then vfork is behaving
-        more like fork.  In either case we needn't worry about clobbering
-        the child's copy of environ.  */
-      environ = save_environ;
-
-      if (!bad_fn && in != STDIN_FILE_NO)
-       if (close (in) < 0)
-         bad_fn = "close";
-      if (!bad_fn && out != STDOUT_FILE_NO)
-       if (close (out) < 0)
-         bad_fn = "close";
-      if (!bad_fn && errdes != STDERR_FILE_NO)
-       if (close (errdes) < 0)
-         bad_fn = "close";
-
-      if (bad_fn)
-       {
-         *err = errno;
-         *errmsg = bad_fn;
-         return (pid_t) -1;
-       }
+       if (bad_fn)
+         {
+           *err = errno;
+           *errmsg = bad_fn;
+           return (pid_t) -1;
+         }
+      }
 
       return pid;
     }