glibc maintains a binary tree of environment strings it malloc()ed
itself. However, it's possible for it to malloc() a string, then find
that an identical string is already in the tree. In this case, the
memory is leaked and is not freed if the application later calls
__libc_freeres(). Fix this by freeing 'new_value' when it's unneeded.
Test case:
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = calloc(100000, 1);
memset(p, 'A', 99999);
setenv("TESTVAR", p, 1);
setenv("TESTVAR", p, 1);
free(p);
}
Leak that was reported by valgrind:
100,008 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x4E6B3D4: __add_to_environ (setenv.c:176)
by 0x4C31B8F: setenv (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x400642: main (in /mnt/tmpfs/a.out)