summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libc/stdlib/getenv.c64
-rw-r--r--tools/regression/environ/Makefile.envctl2
-rw-r--r--tools/regression/environ/envctl.c31
-rw-r--r--tools/regression/environ/envtest.t15
4 files changed, 81 insertions, 31 deletions
diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c
index 2abf7fc..810e671 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)
diff --git a/tools/regression/environ/Makefile.envctl b/tools/regression/environ/Makefile.envctl
index 6298a20..fc90499 100644
--- a/tools/regression/environ/Makefile.envctl
+++ b/tools/regression/environ/Makefile.envctl
@@ -13,4 +13,4 @@ NO_MAN= yes
.include <bsd.prog.mk>
test: ${PROG}
- @sh envtest.t
+ @env -i sh envtest.t
diff --git a/tools/regression/environ/envctl.c b/tools/regression/environ/envctl.c
index 7858211..586314b 100644
--- a/tools/regression/environ/envctl.c
+++ b/tools/regression/environ/envctl.c
@@ -60,7 +60,7 @@ dump_environ(void)
static void
usage(const char *program)
{
- fprintf(stderr, "Usage: %s [-DGUchrt] [-c 1|2|3|4] [-gu name] "
+ fprintf(stderr, "Usage: %s [-DGUchrt] [-c 1|2|3|4] [-bgu name] "
"[-p name=value]\n"
"\t[(-S|-s name) value overwrite]\n\n"
"Options:\n"
@@ -68,6 +68,7 @@ usage(const char *program)
" -G name\t\t\tgetenv(NULL)\n"
" -S value overwrite\t\tsetenv(NULL, value, overwrite)\n"
" -U\t\t\t\tunsetenv(NULL)\n"
+ " -b name\t\t\tblank the 'name=$name' entry, corrupting it\n"
" -c 1|2|3|4\t\t\tClear environ variable using method:\n"
"\t\t\t\t1 - set environ to NULL pointer\n"
"\t\t\t\t2 - set environ[0] to NULL pointer\n"
@@ -98,6 +99,28 @@ print_rtrn_errno(int rtrnVal, const char *eol)
return;
}
+static void
+blank_env(const char *var)
+{
+ char **newenviron;
+ int n, varlen;
+
+ if (environ == NULL)
+ return;
+
+ for (n = 0; environ[n] != NULL; n++)
+ ;
+ newenviron = malloc(sizeof(char *) * (n + 1));
+ varlen = strlen(var);
+ for (; n >= 0; n--) {
+ newenviron[n] = environ[n];
+ if (newenviron[n] != NULL &&
+ strncmp(newenviron[n], var, varlen) == 0 &&
+ newenviron[n][varlen] == '=')
+ newenviron[n] += strlen(newenviron[n]);
+ }
+ environ = newenviron;
+}
int
main(int argc, char **argv)
@@ -114,8 +137,12 @@ main(int argc, char **argv)
}
/* The entire program is basically executed from this loop. */
- while ((arg = getopt(argc, argv, "DGS:Uc:g:hp:rs:tu:")) != -1) {
+ while ((arg = getopt(argc, argv, "DGS:Ub:c:g:hp:rs:tu:")) != -1) {
switch (arg) {
+ case 'b':
+ blank_env(optarg);
+ break;
+
case 'c':
switch (atoi(optarg)) {
case 1:
diff --git a/tools/regression/environ/envtest.t b/tools/regression/environ/envtest.t
index 6b5485a..2c54017 100644
--- a/tools/regression/environ/envtest.t
+++ b/tools/regression/environ/envtest.t
@@ -232,3 +232,18 @@ check_result "${BAR} 0 0 ${BAR} 0 0 ${NULL}"
run_test -r -g FOO -u FOO -g FOO -s FOO ${BAR} 1 -g FOO
check_result "${BAR} 0 0 ${NULL} 0 0 ${BAR}"
+
+
+# corruption (blanking) of environ members.
+export BLANK_ME=
+export AFTER_BLANK=blanked
+run_test -b BLANK_ME -p MORE=vars -g FOO -g BLANK_ME -g AFTER_BLANK
+check_result "0 0 ${FOO} ${NULL} ${AFTER_BLANK}"
+
+run_test -b BLANK_ME -u FOO -g FOO -g AFTER_BLANK
+check_result "0 0 ${NULL} ${AFTER_BLANK}"
+
+export BLANK_ME2=
+export AFTER_BLANKS=blankD
+run_test -b BLANK_ME -b AFTER_BLANK -b BLANK_ME2 -g FOO -g AFTER_BLANKS
+check_result "${FOO} ${AFTER_BLANKS}"
OpenPOWER on IntegriCloud