Subject: please review: unsetenv memory leak fix
To: None <tech-userlevel@netbsd.org>
From: Masaru OKI <oki@netbsd.org>
List: tech-userlevel
Date: 06/28/2003 01:39:55
Hi,
unsetenv(3) doesn't call free(3) with environment variable string.
following diff is fixed the problem.
If it is looks good, I'll commit it later.
--
Masaru OKI <oki@netbsd.org>
Index: __unsetenv13.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/__unsetenv13.c,v
retrieving revision 1.2
diff -u -r1.2 __unsetenv13.c
--- __unsetenv13.c 2003/04/13 17:39:13 1.2
+++ __unsetenv13.c 2003/06/27 14:44:00
@@ -68,6 +68,8 @@
#endif
extern char **environ;
+extern int __environ_alloced;
+extern int *__env_is_malloced;
/*
* unsetenv(name) --
@@ -94,10 +96,13 @@
#endif
rwlock_wrlock(&__environ_lock);
- while (__findenv(name, &offset)) /* if set multiple times */
+ while (__findenv(name, &offset)) { /* if set multiple times */
+ if (__environ_alloced == 1 && __env_is_malloced[offset] == 1)
+ free(environ[offset]);
for (p = &environ[offset];; ++p)
if (!(*p = *(p + 1)))
break;
+ }
rwlock_unlock(&__environ_lock);
#ifndef __LIBC12_SOURCE__
Index: setenv.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/setenv.c,v
retrieving revision 1.22
diff -u -r1.22 setenv.c
--- setenv.c 2003/04/07 13:41:14 1.22
+++ setenv.c 2003/06/27 14:44:01
@@ -61,6 +61,9 @@
extern char **environ;
+int __environ_alloced; /* if allocated space before */
+int *__env_is_malloced;
+
/*
* setenv --
* Set the value of the environmental variable "name" to be
@@ -72,7 +75,6 @@
const char *value;
int rewrite;
{
- static int alloced; /* if allocated space before */
char *c;
const char *cc;
size_t l_value;
@@ -101,21 +103,29 @@
char **p;
for (p = environ, cnt = 0; *p; ++p, ++cnt);
- if (alloced) { /* just increase size */
+ if (__environ_alloced) { /* just increase size */
environ = realloc(environ,
(size_t)(sizeof(char *) * (cnt + 2)));
if (!environ) {
rwlock_unlock(&__environ_lock);
return (-1);
}
+ __env_is_malloced = realloc(__env_is_malloced,
+ (size_t)(sizeof(int) * (cnt + 2)));
}
else { /* get new space */
- alloced = 1; /* copy old entries into it */
+ __environ_alloced = 1; /* copy old entries into it */
p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
if (!p) {
rwlock_unlock(&__environ_lock);
return (-1);
}
+ __env_is_malloced = calloc(cnt, sizeof(int));
+ if (!__env_is_malloced) {
+ free(p);
+ rwlock_unlock(&__environ_lock);
+ return (-1);
+ }
memcpy(p, environ, cnt * sizeof(char *));
environ = p;
}
@@ -124,11 +134,14 @@
}
for (cc = name; *cc && *cc != '='; ++cc)/* no `=' in name */
continue;
+ if (__env_is_malloced[offset] == 1)
+ free(environ[offset]);
if (!(environ[offset] = /* name + `=' + value */
malloc((size_t)((int)(cc - name) + l_value + 2)))) {
rwlock_unlock(&__environ_lock);
return (-1);
}
+ __env_is_malloced[offset] = 1;
for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
for (*c++ = '='; (*c++ = *value++) != '\0'; );
rwlock_unlock(&__environ_lock);