diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2010-08-23 22:31:51 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2010-08-23 22:31:51 +0000 |
commit | f2fa2101698d6e85e65f703e8032356abbf7b14a (patch) | |
tree | 2a4efc39cc26e7886404c089528646dbb90a9fc3 | |
parent | cd20f799577f922d48105b607102b8a9150f4a9b (diff) |
Check for duplicate variables in the environment when setting a value
via setenv() or putenv(). OK miod@
-rw-r--r-- | lib/libc/stdlib/getenv.c | 9 | ||||
-rw-r--r-- | lib/libc/stdlib/setenv.c | 26 |
2 files changed, 24 insertions, 11 deletions
diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c index 5aff11c61ac..fd8482e9e3c 100644 --- a/lib/libc/stdlib/getenv.c +++ b/lib/libc/stdlib/getenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getenv.c,v 1.9 2009/06/03 15:52:16 millert Exp $ */ +/* $OpenBSD: getenv.c,v 1.10 2010/08/23 22:31:50 millert Exp $ */ /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. @@ -36,8 +36,9 @@ char *__findenv(const char *name, int len, int *offset); /* * __findenv -- * Returns pointer to value associated with name, if any, else NULL. + * Starts searching within the environmental array at offset. * Sets offset to be the offset of the name/value combination in the - * environmental array, for use by setenv(3) and unsetenv(3). + * environmental array, for use by putenv(3), setenv(3) and unsetenv(3). * Explicitly removes '=' in argument name. * * This routine *should* be a static; don't use it. @@ -52,7 +53,7 @@ __findenv(const char *name, int len, int *offset) if (name == NULL || environ == NULL) return (NULL); - for (p = environ; (cp = *p) != NULL; ++p) { + for (p = environ + *offset; (cp = *p) != NULL; ++p) { for (np = name, i = len; i && *cp; i--) if (*cp++ != *np++) break; @@ -71,7 +72,7 @@ __findenv(const char *name, int len, int *offset) char * getenv(const char *name) { - int offset; + int offset = 0; const char *np; for (np = name; *np && *np != '='; ++np) diff --git a/lib/libc/stdlib/setenv.c b/lib/libc/stdlib/setenv.c index 89d1e889119..089ab92d38f 100644 --- a/lib/libc/stdlib/setenv.c +++ b/lib/libc/stdlib/setenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: setenv.c,v 1.12 2010/06/29 04:09:34 naddy Exp $ */ +/* $OpenBSD: setenv.c,v 1.13 2010/08/23 22:31:50 millert Exp $ */ /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. @@ -47,7 +47,7 @@ putenv(char *str) { char **P, *cp; size_t cnt; - int offset; + int offset = 0; for (cp = str; *cp && *cp != '='; ++cp) ; @@ -57,7 +57,13 @@ putenv(char *str) } if (__findenv(str, (int)(cp - str), &offset) != NULL) { - environ[offset] = str; + environ[offset++] = str; + /* could be set multiple times */ + while (__findenv(str, (int)(cp - str), &offset)) { + for (P = &environ[offset];; ++P) + if (!(*P = *(P + 1))) + break; + } return (0); } @@ -84,9 +90,9 @@ putenv(char *str) int setenv(const char *name, const char *value, int rewrite) { - char *C; + char *C, **P; const char *np; - int l_value, offset; + int l_value, offset = 0; for (np = name; *np && *np != '='; ++np) ; @@ -99,6 +105,7 @@ setenv(const char *name, const char *value, int rewrite) l_value = strlen(value); if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { + int tmpoff = offset + 1; if (!rewrite) return (0); #if 0 /* XXX - existing entry may not be writable */ @@ -108,9 +115,14 @@ setenv(const char *name, const char *value, int rewrite) return (0); } #endif + /* could be set multiple times */ + while (__findenv(name, (int)(np - name), &tmpoff)) { + for (P = &environ[tmpoff];; ++P) + if (!(*P = *(P + 1))) + break; + } } else { /* create new slot */ size_t cnt; - char **P; for (P = environ; *P != NULL; P++) ; @@ -143,7 +155,7 @@ unsetenv(const char *name) { char **P; const char *np; - int offset; + int offset = 0; if (!name || !*name) { errno = EINVAL; |