1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-05 19:35:52 +03:00
2005-01-20  Ulrich Drepper  <drepper@redhat.com>

	* 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.
This commit is contained in:
Ulrich Drepper
2005-01-20 20:10:02 +00:00
parent f89c41c116
commit 57b47af94b
7 changed files with 170 additions and 116 deletions

View File

@@ -1,3 +1,22 @@
2005-01-20 Ulrich Drepper <drepper@redhat.com>
* 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 <roland@redhat.com> 2005-01-19 Roland McGrath <roland@redhat.com>
[BZ #681] [BZ #681]

View File

@@ -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. # This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or # 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-waitid.c = -fexceptions
CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-getopt.c = -fexceptions CFLAGS-getopt.c = -fexceptions
CFLAGS-wordexp.c = -fexceptions CFLAGS-wordexp.c = -fexceptions -fomit-frame-pointer
CFLAGS-sysconf.c = -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"' CFLAGS-sysconf.c = -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"'
CFLAGS-pathconf.c = -fexceptions CFLAGS-pathconf.c = -fexceptions
CFLAGS-fpathconf.c = -fexceptions CFLAGS-fpathconf.c = -fexceptions
CFLAGS-spawn.c = -fexceptions CFLAGS-spawn.c = -fexceptions -fomit-frame-pointer
CFLAGS-spawnp.c = -fexceptions CFLAGS-spawnp.c = -fexceptions -fomit-frame-pointer
CFLAGS-spawni.c = -fexceptions CFLAGS-spawni.c = -fexceptions -fomit-frame-pointer
CFLAGS-pause.c = -fexceptions CFLAGS-pause.c = -fexceptions
CFLAGS-glob.c = $(uses-callbacks) -fexceptions CFLAGS-glob.c = $(uses-callbacks) -fexceptions
CFLAGS-glob64.c = $(uses-callbacks) -fexceptions CFLAGS-glob64.c = $(uses-callbacks) -fexceptions
CFLAGS-getconf.c = -DGETCONF_DIR='"$(libexecdir)/getconf"' 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 \ tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
--none random --col --color --colour --none random --col --color --colour

View File

@@ -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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#include <alloca.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <stackinfo.h> #include <stackinfo.h>
@@ -33,46 +33,44 @@
int int
execl (const char *path, const char *arg, ...) execl (const char *path, const char *arg, ...)
{ {
size_t argv_max = 1024; #define INITIAL_ARGV_MAX 1024
const char **argv = alloca (argv_max * sizeof (const char *)); size_t argv_max = INITIAL_ARGV_MAX;
unsigned int i; const char *initial_argv[INITIAL_ARGV_MAX];
const char **argv = initial_argv;
va_list args; va_list args;
argv[0] = arg; argv[0] = arg;
va_start (args, arg); va_start (args, arg);
i = 0; unsigned int i = 0;
while (argv[i++] != NULL) while (argv[i++] != NULL)
{ {
if (i == argv_max) if (i == argv_max)
{ {
const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *)); argv_max *= 2;
const char **nptr = realloc (argv == initial_argv ? NULL : argv,
#ifndef _STACK_GROWS_UP argv_max * sizeof (const char *));
if ((char *) nptr + argv_max == (char *) argv) if (nptr == NULL)
{ {
/* Stack grows down. */ if (argv != initial_argv)
argv = (const char **) memcpy (nptr, argv, free (argv);
i * sizeof (const char *)); return -1;
argv_max += i;
} }
else if (argv == initial_argv)
#endif /* We have to copy the already filled-in data ourselves. */
#ifndef _STACK_GROWS_DOWN memcpy (nptr, argv, i * sizeof (const char *));
if ((char *) argv + i == (char *) nptr)
/* Stack grows up. */ argv = nptr;
argv_max += i;
else
#endif
/* We have a hole in the stack. */
argv = (const char **) memcpy (nptr, argv,
i * sizeof (const char *));
} }
argv[i] = va_arg (args, const char *); argv[i] = va_arg (args, const char *);
} }
va_end (args); 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) libc_hidden_def (execl)

View File

@@ -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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#include <alloca.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <stackinfo.h> #include <stackinfo.h>
@@ -29,48 +29,45 @@
int int
execle (const char *path, const char *arg, ...) execle (const char *path, const char *arg, ...)
{ {
size_t argv_max = 1024; #define INITIAL_ARGV_MAX 1024
const char **argv = alloca (argv_max * sizeof (const char *)); size_t argv_max = INITIAL_ARGV_MAX;
const char *const *envp; const char *initial_argv[INITIAL_ARGV_MAX];
unsigned int i; const char **argv = initial_argv;
va_list args; va_list args;
argv[0] = arg; argv[0] = arg;
va_start (args, arg); va_start (args, arg);
i = 0; unsigned int i = 0;
while (argv[i++] != NULL) while (argv[i++] != NULL)
{ {
if (i == argv_max) if (i == argv_max)
{ {
const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *)); argv_max *= 2;
const char **nptr = realloc (argv == initial_argv ? NULL : argv,
#ifndef _STACK_GROWS_UP argv_max * sizeof (const char *));
if ((char *) nptr + argv_max == (char *) argv) if (nptr == NULL)
{ {
/* Stack grows down. */ if (argv != initial_argv)
argv = (const char **) memcpy (nptr, argv, free (argv);
i * sizeof (const char *)); return -1;
argv_max += i;
} }
else if (argv == initial_argv)
#endif /* We have to copy the already filled-in data ourselves. */
#ifndef _STACK_GROWS_DOWN memcpy (nptr, argv, i * sizeof (const char *));
if ((char *) argv + i == (char *) nptr)
/* Stack grows up. */ argv = nptr;
argv_max += i;
else
#endif
/* We have a hole in the stack. */
argv = (const char **) memcpy (nptr, argv,
i * sizeof (const char *));
} }
argv[i] = va_arg (args, const char *); 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); 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) libc_hidden_def (execle)

View File

@@ -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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#include <alloca.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <stackinfo.h> #include <stackinfo.h>
@@ -30,46 +30,44 @@
int int
execlp (const char *file, const char *arg, ...) execlp (const char *file, const char *arg, ...)
{ {
size_t argv_max = 1024; #define INITIAL_ARGV_MAX 1024
const char **argv = alloca (argv_max * sizeof (const char *)); size_t argv_max = INITIAL_ARGV_MAX;
unsigned int i; const char *initial_argv[INITIAL_ARGV_MAX];
const char **argv = initial_argv;
va_list args; va_list args;
argv[0] = arg; argv[0] = arg;
va_start (args, arg); va_start (args, arg);
i = 0; unsigned int i = 0;
while (argv[i++] != NULL) while (argv[i++] != NULL)
{ {
if (i == argv_max) if (i == argv_max)
{ {
const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *)); argv_max *= 2;
const char **nptr = realloc (argv == initial_argv ? NULL : argv,
#ifndef _STACK_GROWS_UP argv_max * sizeof (const char *));
if ((char *) nptr + argv_max == (char *) argv) if (nptr == NULL)
{ {
/* Stack grows down. */ if (argv != initial_argv)
argv = (const char **) memcpy (nptr, argv, free (argv);
i * sizeof (const char *)); return -1;
argv_max += i;
} }
else if (argv == initial_argv)
#endif /* We have to copy the already filled-in data ourselves. */
#ifndef _STACK_GROWS_DOWN memcpy (nptr, argv, i * sizeof (const char *));
if ((char *) argv + i == (char *) nptr)
/* Stack grows up. */ argv = nptr;
argv_max += i;
else
#endif
/* We have a hole in the stack. */
argv = (const char **) memcpy (nptr, argv,
i * sizeof (const char *));
} }
argv[i] = va_arg (args, const char *); argv[i] = va_arg (args, const char *);
} }
va_end (args); 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) libc_hidden_def (execlp)

View File

@@ -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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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 file is accessible but it is not an executable file. Invoke
the shell to interpret it as a script. */ the shell to interpret it as a script. */
static void static char **
internal_function internal_function
script_execute (const char *file, char *const argv[]) allocate_scripts_argv (const char *file, char *const argv[])
{ {
/* Count the arguments. */ /* Count the arguments. */
int argc = 0; int argc = 0;
@@ -36,19 +36,19 @@ script_execute (const char *file, char *const argv[])
; ;
/* Construct an argument list for the shell. */ /* Construct an argument list for the shell. */
{ char **new_argv = (char **) malloc ((argc + 1) * sizeof (char *));
char *new_argv[argc + 1]; if (new_argv != NULL)
new_argv[0] = (char *) _PATH_BSHELL; {
new_argv[1] = (char *) file; new_argv[0] = (char *) _PATH_BSHELL;
while (argc > 1) new_argv[1] = (char *) file;
{ while (argc > 1)
new_argv[argc] = argv[argc - 1]; {
--argc; new_argv[argc] = argv[argc - 1];
} --argc;
}
}
/* Execute the shell. */ return new_argv;
__execve (new_argv[0], new_argv, __environ);
}
} }
@@ -66,42 +66,58 @@ execvp (file, argv)
return -1; return -1;
} }
char **script_argv = NULL;
if (strchr (file, '/') != NULL) if (strchr (file, '/') != NULL)
{ {
/* Don't search when it contains a slash. */ /* Don't search when it contains a slash. */
__execve (file, argv, __environ); __execve (file, argv, __environ);
if (errno == ENOEXEC) 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 else
{ {
int got_eacces = 0; char *path = getenv ("PATH");
char *path, *p, *name; bool path_malloc = false;
size_t len;
size_t pathlen;
path = getenv ("PATH");
if (path == NULL) if (path == NULL)
{ {
/* There is no `PATH' in the environment. /* There is no `PATH' in the environment.
The default search path is the current directory The default search path is the current directory
followed by the path `confstr' returns for `_CS_PATH'. */ followed by the path `confstr' returns for `_CS_PATH'. */
len = confstr (_CS_PATH, (char *) NULL, 0); size_t len = confstr (_CS_PATH, (char *) NULL, 0);
path = (char *) __alloca (1 + len); path = (char *) malloc (1 + len);
if (path == NULL)
return -1;
path[0] = ':'; path[0] = ':';
(void) confstr (_CS_PATH, path + 1, len); (void) confstr (_CS_PATH, path + 1, len);
path_malloc = true;
} }
len = strlen (file) + 1; size_t len = strlen (file) + 1;
pathlen = strlen (path); size_t pathlen = strlen (path);
name = __alloca (pathlen + len + 1); char *name = malloc (pathlen + len + 1);
if (name == NULL)
{
if (path_malloc)
free (path);
return -1;
}
/* Copy the file name at the top. */ /* Copy the file name at the top. */
name = (char *) memcpy (name + pathlen + 1, file, len); name = (char *) memcpy (name + pathlen + 1, file, len);
/* And add the slash. */ /* And add the slash. */
*--name = '/'; *--name = '/';
p = path; bool got_eacces = false;
char *p = path;
do do
{ {
char *startp; char *startp;
@@ -120,7 +136,21 @@ execvp (file, argv)
__execve (startp, argv, __environ); __execve (startp, argv, __environ);
if (errno == ENOEXEC) 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) switch (errno)
{ {
@@ -128,7 +158,7 @@ execvp (file, argv)
/* Record the we got a `Permission denied' error. If we end /* Record the we got a `Permission denied' error. If we end
up finding no executable we can use, we want to diagnose up finding no executable we can use, we want to diagnose
that we did find one but were denied access. */ that we did find one but were denied access. */
got_eacces = 1; got_eacces = true;
case ENOENT: case ENOENT:
case ESTALE: case ESTALE:
case ENOTDIR: case ENOTDIR:
@@ -156,6 +186,11 @@ execvp (file, argv)
/* At least one failure was due to permissions, so report that /* At least one failure was due to permissions, so report that
error. */ error. */
__set_errno (EACCES); __set_errno (EACCES);
free (script_argv);
free (name);
if (path_malloc)
free (path);
} }
/* Return the error from the last attempt (probably ENOENT). */ /* Return the error from the last attempt (probably ENOENT). */

View File

@@ -91,7 +91,7 @@ generated += isomac isomac.out tst-putenvmod.so
CFLAGS-bsearch.c = $(uses-callbacks) CFLAGS-bsearch.c = $(uses-callbacks)
CFLAGS-msort.c = $(uses-callbacks) CFLAGS-msort.c = $(uses-callbacks)
CFLAGS-qsort.c = $(uses-callbacks) CFLAGS-qsort.c = $(uses-callbacks)
CFLAGS-system.c = -fexceptions CFLAGS-system.c = -fexceptions -fomit-frame-pointer
CFLAGS-fmtmsg.c = -fexceptions CFLAGS-fmtmsg.c = -fexceptions
ifneq (,$(filter %REENTRANT, $(defines))) ifneq (,$(filter %REENTRANT, $(defines)))