about summary refs log tree commit diff
path: root/stdlib
diff options
context:
space:
mode:
authorEric Biggers <ebiggers3@gmail.com>2015-01-07 12:10:52 +0530
committerSiddhesh Poyarekar <siddhesh@redhat.com>2015-01-07 12:10:52 +0530
commitd5b1c5ed8bd9515505d4177f105c19ea375106ae (patch)
tree5e7164983b8a3e4f3a16e8069495a46c8c33d7b3 /stdlib
parentfb87ee96d7dd0714d52004e4676629f8d9db732f (diff)
downloadglibc-d5b1c5ed8bd9515505d4177f105c19ea375106ae.tar.gz
glibc-d5b1c5ed8bd9515505d4177f105c19ea375106ae.tar.xz
glibc-d5b1c5ed8bd9515505d4177f105c19ea375106ae.zip
setenv fix memory leak when setting large, duplicate string (BZ #17658)
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)
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/setenv.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/stdlib/setenv.c b/stdlib/setenv.c
index 710da1383c..b60c4f0151 100644
--- a/stdlib/setenv.c
+++ b/stdlib/setenv.c
@@ -217,6 +217,13 @@ __add_to_environ (name, value, combined, replace)
 	      /* And remember the value.  */
 	      STORE_VALUE (np);
 	    }
+#ifdef USE_TSEARCH
+	  else
+	    {
+	      if (__glibc_unlikely (! use_alloca))
+		free (new_value);
+	    }
+#endif
 	}
 
       *ep = np;