From 832c74d935917263bb7f9852230bb39fd47584cc Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 23 Aug 2018 10:21:21 +0000 Subject: [PATCH] [libiberty patch] Fix PGO bootstrap 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 From-SVN: r263807 --- libiberty/ChangeLog | 7 ++ libiberty/pex-unix.c | 163 ++++++++++++++++++++++--------------------- 2 files changed, 90 insertions(+), 80 deletions(-) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 22d995f8cfb..ed07acfa73a 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,10 @@ +2018-08-23 Nathan Sidwell + Martin Liska + + 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 * pex-unix.c (pex_child_error): Delete. diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index ea5ee4c141b..703010bdeae 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -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; } -- 2.30.2