From 57b47af94b3c886ca65e32c41a9f665baaf823f0 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 20 Jan 2005 20:10:02 +0000 Subject: [PATCH] Update. 2005-01-20 Ulrich Drepper * posix/execl.c: Do not allocate potentially large buffers on the stack. * posix/execle.c: Likewise. * posix/execlp.c: Likewise. * posix/execlp.c: Likewise. (script_execute): Removed. (allocate_scripts_argv): New function. Called at most once to allocate memory, not every time a script is run. Adjust caller. * sysdeps/generic/wordexp.c (exec_comm): Add a few TEMP_FAILURE_RETRY. Reorganize code to avoid multiple calls to exec_comm_child. (exec_comm_child): Can now be inlined. * posix/Makefile: Add -fomit-frame-pointer for a few more files. * stdlib/Makefile: Likewise. --- ChangeLog | 19 +++++++++++ posix/Makefile | 17 +++++++--- posix/execl.c | 50 ++++++++++++++--------------- posix/execle.c | 53 +++++++++++++++---------------- posix/execlp.c | 50 ++++++++++++++--------------- posix/execvp.c | 97 +++++++++++++++++++++++++++++++++++++++------------------ stdlib/Makefile | 2 +- 7 files changed, 171 insertions(+), 117 deletions(-) diff --git a/ChangeLog b/ChangeLog index b70a318..0a8077c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2005-01-20 Ulrich Drepper + + * posix/execl.c: Do not allocate potentially large buffers on the + stack. + * posix/execle.c: Likewise. + * posix/execlp.c: Likewise. + * posix/execlp.c: Likewise. + (script_execute): Removed. + (allocate_scripts_argv): New function. Called at most once to + allocate memory, not every time a script is run. Adjust caller. + + * sysdeps/generic/wordexp.c (exec_comm): Add a few + TEMP_FAILURE_RETRY. Reorganize code to avoid multiple calls to + exec_comm_child. + (exec_comm_child): Can now be inlined. + + * posix/Makefile: Add -fomit-frame-pointer for a few more files. + * stdlib/Makefile: Likewise. + 2005-01-19 Roland McGrath [BZ #681] diff --git a/posix/Makefile b/posix/Makefile index bdd3e71..1fdb57c 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-1999, 2000-2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1991-1999, 2000-2003, 2004, 2005 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -138,17 +138,24 @@ CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-waitid.c = -fexceptions CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-getopt.c = -fexceptions -CFLAGS-wordexp.c = -fexceptions +CFLAGS-wordexp.c = -fexceptions -fomit-frame-pointer CFLAGS-sysconf.c = -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"' CFLAGS-pathconf.c = -fexceptions CFLAGS-fpathconf.c = -fexceptions -CFLAGS-spawn.c = -fexceptions -CFLAGS-spawnp.c = -fexceptions -CFLAGS-spawni.c = -fexceptions +CFLAGS-spawn.c = -fexceptions -fomit-frame-pointer +CFLAGS-spawnp.c = -fexceptions -fomit-frame-pointer +CFLAGS-spawni.c = -fexceptions -fomit-frame-pointer CFLAGS-pause.c = -fexceptions CFLAGS-glob.c = $(uses-callbacks) -fexceptions CFLAGS-glob64.c = $(uses-callbacks) -fexceptions CFLAGS-getconf.c = -DGETCONF_DIR='"$(libexecdir)/getconf"' +CFLAGS-execve.c = -fomit-frame-pointer +CFLAGS-fexecve.c = -fomit-frame-pointer +CFLAGS-execv.c = -fomit-frame-pointer +CFLAGS-execle.c = -fomit-frame-pointer +CFLAGS-execl.c = -fomit-frame-pointer +CFLAGS-execvp.c = -fomit-frame-pointer +CFLAGS-execlp.c = -fomit-frame-pointer tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \ --none random --col --color --colour diff --git a/posix/execl.c b/posix/execl.c index 62fd45d..12b59f9 100644 --- a/posix/execl.c +++ b/posix/execl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,94,97,98,99,2002 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,94,97,98,99,2002,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,10 +16,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include #include #include #include +#include #include #include @@ -33,46 +33,44 @@ int execl (const char *path, const char *arg, ...) { - size_t argv_max = 1024; - const char **argv = alloca (argv_max * sizeof (const char *)); - unsigned int i; +#define INITIAL_ARGV_MAX 1024 + size_t argv_max = INITIAL_ARGV_MAX; + const char *initial_argv[INITIAL_ARGV_MAX]; + const char **argv = initial_argv; va_list args; argv[0] = arg; va_start (args, arg); - i = 0; + unsigned int i = 0; while (argv[i++] != NULL) { if (i == argv_max) { - const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *)); - -#ifndef _STACK_GROWS_UP - if ((char *) nptr + argv_max == (char *) argv) + argv_max *= 2; + const char **nptr = realloc (argv == initial_argv ? NULL : argv, + argv_max * sizeof (const char *)); + if (nptr == NULL) { - /* Stack grows down. */ - argv = (const char **) memcpy (nptr, argv, - i * sizeof (const char *)); - argv_max += i; + if (argv != initial_argv) + free (argv); + return -1; } - else -#endif -#ifndef _STACK_GROWS_DOWN - if ((char *) argv + i == (char *) nptr) - /* Stack grows up. */ - argv_max += i; - else -#endif - /* We have a hole in the stack. */ - argv = (const char **) memcpy (nptr, argv, - i * sizeof (const char *)); + if (argv == initial_argv) + /* We have to copy the already filled-in data ourselves. */ + memcpy (nptr, argv, i * sizeof (const char *)); + + argv = nptr; } argv[i] = va_arg (args, const char *); } va_end (args); - return __execve (path, (char *const *) argv, __environ); + int ret = __execve (path, (char *const *) argv, __environ); + if (argv != initial_argv) + free (argv); + + return ret; } libc_hidden_def (execl) diff --git a/posix/execle.c b/posix/execle.c index 2199ebe..70522ad 100644 --- a/posix/execle.c +++ b/posix/execle.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,97,98,99,2002 Free Software Foundation, Inc. +/* Copyright (C) 1991,97,98,99,2002,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,10 +16,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include #include #include #include +#include #include #include @@ -29,48 +29,45 @@ int execle (const char *path, const char *arg, ...) { - size_t argv_max = 1024; - const char **argv = alloca (argv_max * sizeof (const char *)); - const char *const *envp; - unsigned int i; +#define INITIAL_ARGV_MAX 1024 + size_t argv_max = INITIAL_ARGV_MAX; + const char *initial_argv[INITIAL_ARGV_MAX]; + const char **argv = initial_argv; va_list args; argv[0] = arg; va_start (args, arg); - i = 0; + unsigned int i = 0; while (argv[i++] != NULL) { if (i == argv_max) { - const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *)); - -#ifndef _STACK_GROWS_UP - if ((char *) nptr + argv_max == (char *) argv) + argv_max *= 2; + const char **nptr = realloc (argv == initial_argv ? NULL : argv, + argv_max * sizeof (const char *)); + if (nptr == NULL) { - /* Stack grows down. */ - argv = (const char **) memcpy (nptr, argv, - i * sizeof (const char *)); - argv_max += i; + if (argv != initial_argv) + free (argv); + return -1; } - else -#endif -#ifndef _STACK_GROWS_DOWN - if ((char *) argv + i == (char *) nptr) - /* Stack grows up. */ - argv_max += i; - else -#endif - /* We have a hole in the stack. */ - argv = (const char **) memcpy (nptr, argv, - i * sizeof (const char *)); + if (argv == initial_argv) + /* We have to copy the already filled-in data ourselves. */ + memcpy (nptr, argv, i * sizeof (const char *)); + + argv = nptr; } argv[i] = va_arg (args, const char *); } - envp = va_arg (args, const char *const *); + const char *const *envp = va_arg (args, const char *const *); va_end (args); - return __execve (path, (char *const *) argv, (char *const *) envp); + int ret = __execve (path, (char *const *) argv, (char *const *) envp); + if (argv != initial_argv) + free (argv); + + return ret; } libc_hidden_def (execle) diff --git a/posix/execlp.c b/posix/execlp.c index ba8fc74..66996a9 100644 --- a/posix/execlp.c +++ b/posix/execlp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,93,96,97,98,99,2002 Free Software Foundation, Inc. +/* Copyright (C) 1991,93,96,97,98,99,2002,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,10 +16,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include #include #include #include +#include #include #include @@ -30,46 +30,44 @@ int execlp (const char *file, const char *arg, ...) { - size_t argv_max = 1024; - const char **argv = alloca (argv_max * sizeof (const char *)); - unsigned int i; +#define INITIAL_ARGV_MAX 1024 + size_t argv_max = INITIAL_ARGV_MAX; + const char *initial_argv[INITIAL_ARGV_MAX]; + const char **argv = initial_argv; va_list args; argv[0] = arg; va_start (args, arg); - i = 0; + unsigned int i = 0; while (argv[i++] != NULL) { if (i == argv_max) { - const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *)); - -#ifndef _STACK_GROWS_UP - if ((char *) nptr + argv_max == (char *) argv) + argv_max *= 2; + const char **nptr = realloc (argv == initial_argv ? NULL : argv, + argv_max * sizeof (const char *)); + if (nptr == NULL) { - /* Stack grows down. */ - argv = (const char **) memcpy (nptr, argv, - i * sizeof (const char *)); - argv_max += i; + if (argv != initial_argv) + free (argv); + return -1; } - else -#endif -#ifndef _STACK_GROWS_DOWN - if ((char *) argv + i == (char *) nptr) - /* Stack grows up. */ - argv_max += i; - else -#endif - /* We have a hole in the stack. */ - argv = (const char **) memcpy (nptr, argv, - i * sizeof (const char *)); + if (argv == initial_argv) + /* We have to copy the already filled-in data ourselves. */ + memcpy (nptr, argv, i * sizeof (const char *)); + + argv = nptr; } argv[i] = va_arg (args, const char *); } va_end (args); - return execvp (file, (char *const *) argv); + int ret = execvp (file, (char *const *) argv); + if (argv != initial_argv) + free (argv); + + return ret; } libc_hidden_def (execlp) diff --git a/posix/execvp.c b/posix/execvp.c index d6f60c0..d8dce7a 100644 --- a/posix/execvp.c +++ b/posix/execvp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,1995-99,2002,2004,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,9 +26,9 @@ /* The file is accessible but it is not an executable file. Invoke the shell to interpret it as a script. */ -static void +static char ** internal_function -script_execute (const char *file, char *const argv[]) +allocate_scripts_argv (const char *file, char *const argv[]) { /* Count the arguments. */ int argc = 0; @@ -36,19 +36,19 @@ script_execute (const char *file, char *const argv[]) ; /* Construct an argument list for the shell. */ - { - char *new_argv[argc + 1]; - new_argv[0] = (char *) _PATH_BSHELL; - new_argv[1] = (char *) file; - while (argc > 1) - { - new_argv[argc] = argv[argc - 1]; - --argc; - } - - /* Execute the shell. */ - __execve (new_argv[0], new_argv, __environ); - } + char **new_argv = (char **) malloc ((argc + 1) * sizeof (char *)); + if (new_argv != NULL) + { + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) file; + while (argc > 1) + { + new_argv[argc] = argv[argc - 1]; + --argc; + } + } + + return new_argv; } @@ -66,42 +66,58 @@ execvp (file, argv) return -1; } + char **script_argv = NULL; + if (strchr (file, '/') != NULL) { /* Don't search when it contains a slash. */ __execve (file, argv, __environ); if (errno == ENOEXEC) - script_execute (file, argv); + { + script_argv = allocate_scripts_argv (file, argv); + if (script_argv != NULL) + { + __execve (script_argv[0], script_argv, __environ); + + free (script_argv); + } + } } else { - int got_eacces = 0; - char *path, *p, *name; - size_t len; - size_t pathlen; - - path = getenv ("PATH"); + char *path = getenv ("PATH"); + bool path_malloc = false; if (path == NULL) { /* There is no `PATH' in the environment. The default search path is the current directory followed by the path `confstr' returns for `_CS_PATH'. */ - len = confstr (_CS_PATH, (char *) NULL, 0); - path = (char *) __alloca (1 + len); + size_t len = confstr (_CS_PATH, (char *) NULL, 0); + path = (char *) malloc (1 + len); + if (path == NULL) + return -1; path[0] = ':'; (void) confstr (_CS_PATH, path + 1, len); + path_malloc = true; } - len = strlen (file) + 1; - pathlen = strlen (path); - name = __alloca (pathlen + len + 1); + size_t len = strlen (file) + 1; + size_t pathlen = strlen (path); + char *name = malloc (pathlen + len + 1); + if (name == NULL) + { + if (path_malloc) + free (path); + return -1; + } /* Copy the file name at the top. */ name = (char *) memcpy (name + pathlen + 1, file, len); /* And add the slash. */ *--name = '/'; - p = path; + bool got_eacces = false; + char *p = path; do { char *startp; @@ -120,7 +136,21 @@ execvp (file, argv) __execve (startp, argv, __environ); if (errno == ENOEXEC) - script_execute (startp, argv); + { + if (script_argv == NULL) + { + script_argv = allocate_scripts_argv (file, argv); + if (script_argv == NULL) + { + /* A possible EACCES error is not as important as + the ENOMEM. */ + got_eacces = false; + break; + } + } + + __execve (script_argv[0], script_argv, __environ); + } switch (errno) { @@ -128,7 +158,7 @@ execvp (file, argv) /* Record the we got a `Permission denied' error. If we end up finding no executable we can use, we want to diagnose that we did find one but were denied access. */ - got_eacces = 1; + got_eacces = true; case ENOENT: case ESTALE: case ENOTDIR: @@ -156,6 +186,11 @@ execvp (file, argv) /* At least one failure was due to permissions, so report that error. */ __set_errno (EACCES); + + free (script_argv); + free (name); + if (path_malloc) + free (path); } /* Return the error from the last attempt (probably ENOENT). */ diff --git a/stdlib/Makefile b/stdlib/Makefile index b766fb8..2e45ae1 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -91,7 +91,7 @@ generated += isomac isomac.out tst-putenvmod.so CFLAGS-bsearch.c = $(uses-callbacks) CFLAGS-msort.c = $(uses-callbacks) CFLAGS-qsort.c = $(uses-callbacks) -CFLAGS-system.c = -fexceptions +CFLAGS-system.c = -fexceptions -fomit-frame-pointer CFLAGS-fmtmsg.c = -fexceptions ifneq (,$(filter %REENTRANT, $(defines))) -- 2.7.4