[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15531] trunk/blender/source/blender/ blenlib/intern/storage.c: Memory leak fix (found with Valgrind)

André Pinto andresusanopinto at gmail.com
Sat Jul 12 04:36:40 CEST 2008


According to the manpage of getpwuid:

"The return value may point to static area, and may be overwritten by
subsequent calls to getpwent(3),  getpwnam(), or getpwuid()."

As so its memory should not be freed... but considering Genscher found
a memory issue with it.. it seems that some implementations may expect
the user to free the memory.. but others return static memory.

The alternative and also thread safe is the function
"int getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t
buflen, struct passwd **pwbufp);

Which is available on: _POSIX_C_SOURCE || _XOPEN_SOURCE || _BSD_SOURCE
|| _SVID_SOURCE
I am not sure whether this matches all targets of blender.. but I hope so.

Here is the patch:

Index: source/blender/blenlib/intern/storage.c
===================================================================
--- source/blender/blenlib/intern/storage.c	(revision 15531)
+++ source/blender/blenlib/intern/storage.c	(working copy)
@@ -42,6 +42,7 @@

 #ifndef WIN32
 #include <dirent.h>
+#include <errno.h>
 #endif

 #include <time.h>
@@ -337,6 +338,11 @@
 #ifdef WIN32
 	__int64 st_size;
 #else
+	//buffer to getpwuid_r
+	char *buffer = NULL;
+	size_t bufferlen = 1024;
+//	long int initlen = sysconf(_SC_GETGR_R_SIZE_MAX);
+
 	off_t st_size;
 #endif
 	
@@ -345,6 +351,10 @@
 	time_t zero= 0;

 	file = &files[0];
+
+#ifndef WIN32
+	buffer = (char*)malloc( bufferlen );
+#endif
 	
 	for(num=0;num<actnum;num++){
 #ifdef WIN32
@@ -378,14 +388,33 @@
 		strcpy(files[num].owner,"user");
 #else
 		{
-			struct passwd *pwuser;
-			pwuser = getpwuid(files[num].s.st_uid);
-			if ( pwuser ) {
-			strcpy(files[num].owner, pwuser->pw_name);
-			free(pwuser);
-			} else {
+			struct passwd result;
+			struct passwd *resultp = NULL;
+
+			while(getpwuid_r(files[num].s.st_uid, &result, buffer, bufferlen,
&resultp) == ERANGE)
+			{
+				char *newbuffer;
+				size_t newlen = 2*bufferlen;
+
+				if(newlen < bufferlen)
+					break;	//Overflow
+
+				newbuffer = realloc(buffer, newlen);
+				if(newbuffer == NULL)
+					break;	//Out of memory
+
+				buffer = newbuffer;
+				bufferlen = newlen;
+			}
+	
+			if(resultp)
+			{
+				strncpy(files[num].owner, resultp->pw_name, sizeof( files[num].owner) );
+				files[num].owner[ sizeof(files[num].owner)-1] = 0;
+			}
+			else
 				sprintf(files[num].owner, "%d", files[num].s.st_uid);
-            }
+	
 		}
 #endif

@@ -446,6 +475,12 @@

 		file++;
 	}
+
+#ifndef WIN32
+	if(buffer)
+		free(buffer);
+#endif
+
 }

 unsigned int BLI_getdir(char *dirname,  struct direntry **filelist)


More information about the Bf-committers mailing list