Patch to fix problem with refering environ
Michael Meissner
meissner@redhat.com
Tue Oct 3 15:15:00 GMT 2000
The following patch goes through some hoops to make sure that environ
is only referenced via a statically intiialized pointer. The case I
was working on showed up when the user defined their own environ and
compiled it with -G 0, while the library was compiled with a default
of -G 8, and the linker reported that environ was too far away from
the global pointer. I have also worked on shared library systems that
had similar behavior for library data is used by the library but
defined by the user, so this fix fixes that rare case as well.
2000-10-03 Michael Meissner <meissner@redhat.com>
* libc/posix/execl.c (execl): Don't reference environ directly,
reference it only via a static pointer to avoid problems with some
shared library systems and with different uses of small data where
the user specifies his own version of environ.
* libc/posix/execv.c (execv): Ditto.
* libc/stdlib/getenv_r.c (_findenv_r): Ditto.
* libc/stdlib/setenv_r.c (_setenv_r,_unsetenv_r): Ditto.
* libc/stdlib/system.c (system, !cygwin32 case): Ditto.
* libc/stdlib/getenv.c (environ): Delete unused reference to
environ.
* libc/stdlib/getenv_r.c: Make initial comment friendlier to emacs
colorization.
* libc/stdlib/system.c: Ditto.
*** newlib/libc/posix/execl.c.~1~ Thu Feb 17 14:39:47 2000
--- newlib/libc/posix/execl.c Tue Oct 3 18:05:01 2000
***************
*** 6,11 ****
--- 6,16 ----
#include <_ansi.h>
#include <unistd.h>
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
#ifdef _HAVE_STDC
#include <stdarg.h>
*************** execl (path, arg0, va_alist)
*** 38,42 ****
while (argv[i++] != NULL);
va_end (args);
! return _execve (path, (char * _CONST *) argv, environ);
}
--- 43,47 ----
while (argv[i++] != NULL);
va_end (args);
! return _execve (path, (char * _CONST *) argv, *p_environ);
}
*** newlib/libc/posix/execv.c.~1~ Thu Feb 17 14:39:47 2000
--- newlib/libc/posix/execv.c Tue Oct 3 18:05:18 2000
***************
*** 6,15 ****
#include <_ansi.h>
#include <unistd.h>
int
_DEFUN (execv, (path, argv),
const char *path _AND
char * const argv[])
{
! return _execve (path, (char * _CONST *) argv, environ);
}
--- 6,20 ----
#include <_ansi.h>
#include <unistd.h>
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
int
_DEFUN (execv, (path, argv),
const char *path _AND
char * const argv[])
{
! return _execve (path, (char * _CONST *) argv, *p_environ);
}
*** newlib/libc/stdlib/getenv.c.~1~ Thu Feb 17 14:39:47 2000
--- newlib/libc/stdlib/getenv.c Tue Oct 3 18:05:35 2000
*************** TRAD_SYNOPSIS
*** 18,24 ****
DESCRIPTION
<<getenv>> searches the list of environment variable names and values
! (using the global pointer `<<char **environ>>') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<getenv>> returns a pointer to the associated value.
--- 18,24 ----
DESCRIPTION
<<getenv>> searches the list of environment variable names and values
! (using the global pointer ``<<char **environ>>'') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<getenv>> returns a pointer to the associated value.
*************** variables vary from one system to anothe
*** 39,45 ****
*/
/*
! * Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
--- 39,45 ----
*/
/*
! * Copyright (c) 1987, 2000 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
*************** variables vary from one system to anothe
*** 62,69 ****
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
-
- extern char **environ;
/*
* _findenv --
--- 62,67 ----
*** newlib/libc/stdlib/getenv_r.c.~1~ Thu Feb 17 14:39:47 2000
--- newlib/libc/stdlib/getenv_r.c Tue Oct 3 18:05:54 2000
*************** TRAD_SYNOPSIS
*** 19,25 ****
DESCRIPTION
<<_getenv_r>> searches the list of environment variable names and values
! (using the global pointer `<<char **environ>>') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<_getenv_r>> returns a pointer to the associated value.
--- 19,25 ----
DESCRIPTION
<<_getenv_r>> searches the list of environment variable names and values
! (using the global pointer ``<<char **environ>>'') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<_getenv_r>> returns a pointer to the associated value.
*************** variables vary from one system to anothe
*** 65,70 ****
--- 65,75 ----
extern char **environ;
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
/*
* _findenv --
* Returns pointer to value associated with name, if any, else NULL.
*************** _DEFUN (_findenv_r, (reent_ptr, name, of
*** 89,95 ****
/* In some embedded systems, this does not get set. This protects
newlib from dereferencing a bad pointer. */
! if (!environ)
return NULL;
c = name;
--- 94,100 ----
/* In some embedded systems, this does not get set. This protects
newlib from dereferencing a bad pointer. */
! if (!*p_environ)
return NULL;
c = name;
*************** _DEFUN (_findenv_r, (reent_ptr, name, of
*** 100,110 ****
len++;
}
! for (p = environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
! *offset = p - environ;
ENV_UNLOCK;
return (char *) (++c);
}
--- 105,115 ----
len++;
}
! for (p = *p_environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
! *offset = p - *p_environ;
ENV_UNLOCK;
return (char *) (++c);
}
*** newlib/libc/stdlib/setenv_r.c.~1~ Mon Apr 17 13:10:17 2000
--- newlib/libc/stdlib/setenv_r.c Tue Oct 3 18:06:15 2000
***************
*** 29,34 ****
--- 29,41 ----
#include <string.h>
#include "envlock.h"
+ extern char **environ;
+
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
/* _findenv_r is defined in getenv_r.c. */
extern char *_findenv_r _PARAMS ((struct _reent *, const char *, int *));
*************** _DEFUN (_setenv_r, (reent_ptr, name, val
*** 45,51 ****
_CONST char *value _AND
int rewrite)
{
- extern char **environ;
static int alloced; /* if allocated space before */
register char *C;
int l_value, offset;
--- 52,57 ----
*************** _DEFUN (_setenv_r, (reent_ptr, name, val
*** 74,85 ****
register int cnt;
register char **P;
! for (P = environ, cnt = 0; *P; ++P, ++cnt);
if (alloced)
{ /* just increase size */
! environ = (char **) _realloc_r (reent_ptr, (char *) environ,
! (size_t) (sizeof (char *) * (cnt + 2)));
! if (!environ)
{
ENV_UNLOCK;
return -1;
--- 80,91 ----
register int cnt;
register char **P;
! for (P = *p_environ, cnt = 0; *P; ++P, ++cnt);
if (alloced)
{ /* just increase size */
! *p_environ = (char **) _realloc_r (reent_ptr, (char *) environ,
! (size_t) (sizeof (char *) * (cnt + 2)));
! if (!*p_environ)
{
ENV_UNLOCK;
return -1;
*************** _DEFUN (_setenv_r, (reent_ptr, name, val
*** 94,113 ****
ENV_UNLOCK;
return (-1);
}
! bcopy ((char *) environ, (char *) P, cnt * sizeof (char *));
! environ = P;
}
! environ[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
! if (!(environ[offset] = /* name + `=' + value */
_malloc_r (reent_ptr, (size_t) ((int) (C - name) + l_value + 2))))
{
ENV_UNLOCK;
return -1;
}
! for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
for (*C++ = '='; (*C++ = *value++) != 0;);
ENV_UNLOCK;
--- 100,119 ----
ENV_UNLOCK;
return (-1);
}
! bcopy ((char *) *p_environ, (char *) P, cnt * sizeof (char *));
! *p_environ = P;
}
! (*p_environ)[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
! if (!((*p_environ)[offset] = /* name + `=' + value */
_malloc_r (reent_ptr, (size_t) ((int) (C - name) + l_value + 2))))
{
ENV_UNLOCK;
return -1;
}
! for (C = (*p_environ)[offset]; (*C = *name++) && *C != '='; ++C);
for (*C++ = '='; (*C++ = *value++) != 0;);
ENV_UNLOCK;
*************** _DEFUN (_unsetenv_r, (reent_ptr, name),
*** 124,137 ****
struct _reent *reent_ptr _AND
_CONST char *name)
{
- extern char **environ;
register char **P;
int offset;
ENV_LOCK;
while (_findenv_r (reent_ptr, name, &offset)) /* if set multiple times */
! for (P = &environ[offset];; ++P)
if (!(*P = *(P + 1)))
break;
--- 130,142 ----
struct _reent *reent_ptr _AND
_CONST char *name)
{
register char **P;
int offset;
ENV_LOCK;
while (_findenv_r (reent_ptr, name, &offset)) /* if set multiple times */
! for (P = &(*p_environ)[offset];; ++P)
if (!(*P = *(P + 1)))
break;
*** newlib/libc/stdlib/system.c.~1~ Tue Oct 3 18:03:04 2000
--- newlib/libc/stdlib/system.c Tue Oct 3 18:06:38 2000
*************** DESCRIPTION
*** 27,33 ****
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
! Use `<<system(NULL)>>' to test whether your system has <</bin/sh>>
available.
The alternate function <<_system_r>> is a reentrant version. The
--- 27,33 ----
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
! Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
available.
The alternate function <<_system_r>> is a reentrant version. The
*************** system (s)
*** 107,112 ****
--- 107,119 ----
#endif
#if defined (unix) && !defined (__CYGWIN__)
+ extern char **environ;
+
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
static int
do_system (ptr, s)
struct _reent *ptr;
*************** do_system (ptr, s)
*** 114,120 ****
{
char *argv[4];
int pid, status;
- extern char **environ;
argv[0] = "sh";
argv[1] = "-c";
--- 121,126 ----
*************** do_system (ptr, s)
*** 123,129 ****
if ((pid = _fork_r (ptr)) == 0)
{
! _execve ("/bin/sh", argv, environ);
exit (100);
}
else if (pid == -1)
--- 129,135 ----
if ((pid = _fork_r (ptr)) == 0)
{
! _execve ("/bin/sh", argv, *p_environ);
exit (100);
}
else if (pid == -1)
--
Michael Meissner, Red Hat, Inc.
PMB 198, 174 Littleton Road #3, Westford, Massachusetts 01886, USA
Work: meissner@redhat.com phone: +1 978-486-9304
Non-work: meissner@spectacle-pond.org fax: +1 978-692-4482
More information about the Newlib
mailing list