aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBrian Feldman <green@FreeBSD.org>2009-12-01 05:04:31 +0000
committerBrian Feldman <green@FreeBSD.org>2009-12-01 05:04:31 +0000
commit20f492f0ebaac48ba6f70c67e93e6b01578bc3e6 (patch)
tree4dd69d3b32100a3a44a49bb2deca1681144fe2ab /lib
parentf349fbc4a6783e796c88d6b7e710ad6755346866 (diff)
downloadsrc-20f492f0ebaac48ba6f70c67e93e6b01578bc3e6.tar.gz
src-20f492f0ebaac48ba6f70c67e93e6b01578bc3e6.zip
Do not gratuitously fail *env(3) operations due to corrupt ('='-less)
**environ entries. This puts non-getenv(3) operations in line with getenv(3) in that bad environ entries do not cause all operations to fail. There is still some inconsistency in that getenv(3) in the absence of any environment-modifying operation does not emit corrupt environ entry warnings. I also fixed another inconsistency in getenv(3) where updating the global environ pointer would not be reflected in the return values. It would have taken an intermediary setenv(3)/putenv(3)/unsetenv(3) in order to see the change.
Notes
Notes: svn path=/head/; revision=199983
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/getenv.c64
1 files changed, 36 insertions, 28 deletions
diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c
index 2abf7fc7b01e..810e67141a43 100644
--- a/lib/libc/stdlib/getenv.c
+++ b/lib/libc/stdlib/getenv.c
@@ -96,6 +96,8 @@ static int envVarsTotal = 0;
/* Deinitialization of new environment. */
static void __attribute__ ((destructor)) __clean_env_destructor(void);
+/* Resetting the environ pointer will affect the env functions. */
+static int __merge_environ(void);
/*
@@ -190,6 +192,9 @@ __findenv_environ(const char *name, size_t nameLen)
{
int envNdx;
+ if (environ == NULL)
+ return (NULL);
+
/* Find variable within environ. */
for (envNdx = 0; environ[envNdx] != NULL; envNdx++)
if (strncmpeq(environ[envNdx], name, nameLen))
@@ -328,6 +333,7 @@ __build_env(void)
{
char **env;
int activeNdx;
+ int checking;
int envNdx;
int savedErrno;
size_t nameLen;
@@ -339,6 +345,23 @@ __build_env(void)
/* Count environment variables. */
for (env = environ, envVarsTotal = 0; *env != NULL; env++)
envVarsTotal++;
+ /* Remove any corrupt variable entries, but do not error out. */
+ checking = 0;
+ while (checking < envVarsTotal) {
+ if (strchr(environ[checking], '=') != NULL) {
+ checking++;
+ } else {
+ __env_warnx(CorruptEnvValueMsg,
+ environ[checking], strlen(environ[checking]));
+ /*
+ * Pull back all remaining entries from checking + 1
+ * through envVarsTotal, including the NULL at the end.
+ */
+ memmove(&environ[checking], &environ[checking + 1],
+ sizeof(char *) * (envVarsTotal - checking));
+ envVarsTotal--;
+ }
+ }
envVarsSize = envVarsTotal * 2;
/* Create new environment. */
@@ -353,18 +376,8 @@ __build_env(void)
strdup(environ[envVarsTotal - envNdx - 1]);
if (envVars[envNdx].name == NULL)
goto Failure;
- envVars[envNdx].value = strchr(envVars[envNdx].name, '=');
- if (envVars[envNdx].value != NULL) {
- envVars[envNdx].value++;
- envVars[envNdx].valueSize =
- strlen(envVars[envNdx].value);
- } else {
- __env_warnx(CorruptEnvValueMsg, envVars[envNdx].name,
- strlen(envVars[envNdx].name));
- errno = EFAULT;
- goto Failure;
- }
-
+ envVars[envNdx].value = strchr(envVars[envNdx].name, '=') + 1;
+ envVars[envNdx].valueSize = strlen(envVars[envNdx].value);
/*
* Find most current version of variable to make active. This
* will prevent multiple active variables from being created
@@ -426,22 +439,18 @@ getenv(const char *name)
}
/*
- * An empty environment (environ or its first value) regardless if
- * environ has been copied before will return a NULL.
- *
- * If the environment is not empty, find an environment variable via
- * environ if environ has not been copied via an *env() call or been
- * replaced by a running program, otherwise, use the rebuilt
- * environment.
+ * If we have not already allocated memory by performing
+ * write operations on the environment, avoid doing so now.
*/
- if (environ == NULL || environ[0] == NULL)
- return (NULL);
- else if (envVars == NULL || environ != intEnviron)
+ if (envVars == NULL)
return (__findenv_environ(name, nameLen));
- else {
- envNdx = envVarsTotal - 1;
- return (__findenv(name, nameLen, &envNdx, true));
- }
+
+ /* Synchronize environment. */
+ if (__merge_environ() == -1)
+ return (NULL);
+
+ envNdx = envVarsTotal - 1;
+ return (__findenv(name, nameLen, &envNdx, true));
}
@@ -559,8 +568,7 @@ __merge_environ(void)
if ((equals = strchr(*env, '=')) == NULL) {
__env_warnx(CorruptEnvValueMsg, *env,
strlen(*env));
- errno = EFAULT;
- return (-1);
+ continue;
}
if (__setenv(*env, equals - *env, equals + 1,
1) == -1)