diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2013-02-14 13:14:18 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2013-02-14 13:14:47 -0800 |
commit | a828bb24ee96386201c4236ea917677b6c536c7d (patch) | |
tree | 2a64c9ee1b5ad7fb8bf19374bfbabf1f6e2dfa4a /lib/putenv.c | |
parent | 142eb2ee2f26e522b7ab0d8fefb0b3c34201f208 (diff) | |
download | gnulib-a828bb24ee96386201c4236ea917677b6c536c7d.tar.gz |
putenv: fix heap corruption with mixed putenv/_putenv
Problem reported by Michael Goffioul in
<http://lists.gnu.org/archive/html/bug-gnulib/2013-02/msg00061.html>.
* lib/putenv.c (putenv) [HAVE__PUTENV]:
Rely on _putenv to allocate the new environment.
* m4/putenv.m4 (gl_PREREQ_PUTENV): New macro.
* modules/putenv (configure.ac): Use it.
Diffstat (limited to 'lib/putenv.c')
-rw-r--r-- | lib/putenv.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/putenv.c b/lib/putenv.c index 5f0fedaf9c..0ec392f866 100644 --- a/lib/putenv.c +++ b/lib/putenv.c @@ -115,6 +115,37 @@ putenv (char *string) if (*ep == NULL) { +#if HAVE__PUTENV + /* Rely on _putenv to allocate the new environment. If other + parts of the application use _putenv, the !HAVE__PUTENV code + would fight over who owns the environ vector, causing a crash. */ + if (name_end[1]) + return _putenv (string); + else + { + /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME=x") + to allocate the environ vector and then replace the new + entry with "NAME=". */ + int putenv_result, putenv_errno; + char *name_x = malloc (name_end - string + sizeof "=x"); + if (!name_x) + return -1; + memcpy (name_x, string, name_end - string + 1); + name_x[name_end - string + 1] = 'x'; + name_x[name_end - string + 2] = 0; + putenv_result = _putenv (name_x); + putenv_errno = errno; + for (ep = environ; *ep; ep++) + if (*ep == name_x) + { + *ep = string; + break; + } + free (name_x); + __set_errno (putenv_errno); + return putenv_result; + } +#else static char **last_environ = NULL; char **new_environ = (char **) malloc ((size + 2) * sizeof (char *)); if (new_environ == NULL) @@ -126,6 +157,7 @@ putenv (char *string) free (last_environ); last_environ = new_environ; environ = new_environ; +#endif } else *ep = string; |