Subject: Re: please review: unsetenv memory leak fix
To: None <tech-userlevel@netbsd.org>
From: Masaru OKI <oki@netbsd.org>
List: tech-userlevel
Date: 06/29/2003 01:20:04
On Sat, 28 Jun 2003 17:29:19 +0900
Masaru OKI <oki@netbsd.org> wrote:
> it doesn't compile. sorry, please wait next patch...
here.
comments?
Index: stdlib/__unsetenv13.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/__unsetenv13.c,v
retrieving revision 1.2
diff -u -r1.2 __unsetenv13.c
--- stdlib/__unsetenv13.c 2003/04/13 17:39:13 1.2
+++ stdlib/__unsetenv13.c 2003/06/28 15:59:28
@@ -68,6 +68,7 @@
#endif
extern char **environ;
+extern char **__alloced_env;
/*
* unsetenv(name) --
@@ -81,7 +82,7 @@
unsetenv(name)
const char *name;
{
- char **p;
+ char **p, **mp;
int offset;
_DIAGASSERT(name != NULL);
@@ -94,10 +95,16 @@
#endif
rwlock_wrlock(&__environ_lock);
- while (__findenv(name, &offset)) /* if set multiple times */
- for (p = &environ[offset];; ++p)
+ while (__findenv(name, &offset)) { /* if set multiple times */
+ if (__alloced_env != 0 && __alloced_env[offset] != 0)
+ free(__alloced_env[offset]);
+ for (p = &environ[offset], mp = &__alloced_env[offset];;
+ ++p, ++mp) {
if (!(*p = *(p + 1)))
break;
+ *mp = *(mp + 1);
+ }
+ }
rwlock_unlock(&__environ_lock);
#ifndef __LIBC12_SOURCE__
Index: stdlib/setenv.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/setenv.c,v
retrieving revision 1.22
diff -u -r1.22 setenv.c
--- stdlib/setenv.c 2003/04/07 13:41:14 1.22
+++ stdlib/setenv.c 2003/06/28 15:59:28
@@ -61,6 +61,8 @@
extern char **environ;
+char **__alloced_env = 0; /* if allocated space before */
+
/*
* setenv --
* Set the value of the environmental variable "name" to be
@@ -72,7 +74,6 @@
const char *value;
int rewrite;
{
- static int alloced; /* if allocated space before */
char *c;
const char *cc;
size_t l_value;
@@ -101,16 +102,28 @@
char **p;
for (p = environ, cnt = 0; *p; ++p, ++cnt);
- if (alloced) { /* just increase size */
+ if (__alloced_env) { /* just increase size */
environ = realloc(environ,
(size_t)(sizeof(char *) * (cnt + 2)));
if (!environ) {
rwlock_unlock(&__environ_lock);
return (-1);
}
+ __alloced_env = realloc(__alloced_env,
+ (size_t)(sizeof(char *) * (cnt + 1)));
+ if (!__alloced_env) {
+ rwlock_unlock(&__environ_lock);
+ return (-1);
+ }
+ __alloced_env[cnt] = 0;
}
else { /* get new space */
- alloced = 1; /* copy old entries into it */
+ /* copy old entries into it */
+ __alloced_env = calloc(cnt + 1, sizeof(char *));
+ if (!__alloced_env) {
+ rwlock_unlock(&__environ_lock);
+ return (-1);
+ }
p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
if (!p) {
rwlock_unlock(&__environ_lock);
@@ -124,11 +137,14 @@
}
for (cc = name; *cc && *cc != '='; ++cc)/* no `=' in name */
continue;
+ if (__alloced_env[offset] != 0)
+ free(__alloced_env[offset]);
if (!(environ[offset] = /* name + `=' + value */
malloc((size_t)((int)(cc - name) + l_value + 2)))) {
rwlock_unlock(&__environ_lock);
return (-1);
}
+ __alloced_env[offset] = environ[offset];
for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
for (*c++ = '='; (*c++ = *value++) != '\0'; );
rwlock_unlock(&__environ_lock);
--
Masaru OKI <oki@netbsd.org>