From khana@gaffer.adm.intelsat.int  Fri May 12 13:05:56 2000
Return-Path: <khana@gaffer.adm.intelsat.int>
Received: from iserv.intelsat.int (iserv.intelsat.int [164.86.102.11])
	by hub.freebsd.org (Postfix) with ESMTP id 304BA37C35F
	for <FreeBSD-gnats-submit@FreeBSD.ORG>; Fri, 12 May 2000 13:03:36 -0700 (PDT)
	(envelope-from khana@gaffer.adm.intelsat.int)
Received: from pc2.adm.intelsat.int ([164.86.36.13]) by iserv.intelsat.int
          (Post.Office MTA v3.1.2 release (PO203-101c)
          ID# 0-49113U1000L2S100) with ESMTP id AAA7010;
          Fri, 12 May 2000 16:03:25 -0400
Received: (from smap@localhost) by pc2.adm.intelsat.int (8.8.6 (PHNE_14041)/8.6.10) id QAA24099; Fri, 12 May 2000 16:03:30 -0400 (EDT)
Received: from gaffer.adm.intelsat.int(164.86.39.103) by pc2 via smap (V2.1)
	id xma023974; Fri, 12 May 00 20:02:05 GMT
Received: (from khana@localhost) by gaffer.adm.intelsat.int (8.8.6 (PHNE_17135)/8.7.1) id VAA17697; Fri, 12 May 2000 21:02:05 +0100 (BST)
Message-Id: <200005122002.VAA17697@gaffer.adm.intelsat.int>
Date: Fri, 12 May 2000 21:02:05 +0100 (BST)
From: Abdul Khan <khana@kcm.adm.intelsat.int>
Sender: khana@gaffer.adm.intelsat.int
To: FreeBSD-gnats-submit@FreeBSD.ORG, jeremyp@gsmx07.alcatel.com.au
Subject: memory leak in putenv

>Number:         18519
>Category:       bin
>Synopsis:       memory leak in putenv
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 12 13:10:01 PDT 2000
>Closed-Date:    Sat Jun 2 02:00:28 PDT 2001
>Last-Modified:  Sat Jun 02 02:01:30 PDT 2001
>Originator:     
>Release:        
>Organization:
>Environment:
>Description:
 sorry about the last one.. i was a little too quick on the draw :)
 
 this one should work:
 
 #include <iostream.h>
 #include <stdlib.h>
 
 extern char** environ;
 
 class Exception
 {
 	public:
 		virtual char* getErrorMessage() = 0;
 };
 
 class NullPointerException : public Exception
 {
 	public:
 		virtual char* getErrorMessage() 
 		{
 			return "Null Pointer Exception";
 		};	
 };
 
 class EnvironmentVariable 
 {
 	public:
 
 		EnvironmentVariable(char* variable_name) 
 		{ 
 			if (!variable_name) throw NullPointerException();
 			else name = strdup(variable_name); 
 			setEnvironmentVariableOneTime=false;
 		};
 
 		void setEnv(char* value)
 		{
 			int i = 0, j = 0;
 			while (environ[i])
 			{
 				while (name[j] && environ[i][j] &&
 							name[j] == environ[i][j]) j++;
 				if (environ[i][j] == '=' && !name[j]) 
 				{
 					if (setEnvironmentVariableOneTime)
 					{
 						environ[i] = (char*) realloc (environ[i],
 												sizeof(char)*
 												(strlen (value) + strlen (name) + 1 + 1));
 						sprintf(environ[i], "%s=%s", name, value);
 					}
 					else
 					{
 					int k = i;
 					while (environ[k]) k++;
 					char** new_environ = (char**) malloc(sizeof(char*)*(k+1));
 					for(int n=0;n<k;n++)
 					{
 						new_environ[n] = (char*)
 									malloc(sizeof(char)*(strlen(environ[n])+1));
 						strcpy(new_environ[n], environ[n]);
 					}
 					new_environ[n]=NULL;					
 					new_environ[i] = (char*) realloc (new_environ[i],
 								sizeof(char)*
 								(strlen (value) + strlen (name) + 1 + 1));
 					sprintf(new_environ[i], "%s=%s", name, value);
 					clearenv();
 					environ=new_environ;
 					}
 					break;
 				}
 				i++;
 			}
 			if (!environ[i]) 
 			{
 				char* new_env = 
 						(char*) malloc(sizeof(char)*
 								(strlen (value) + strlen (name) + 1 + 1));
 				sprintf(new_env, "%s=%s", name, value);
 				putenv(new_env);
 			}
 			else
 			{
 				setEnvironmentVariableOneTime = true;
 			}				
 		}
 
 		void setEnvWithLeak(char* value)
 		{
 			char* env = (char *) malloc (sizeof(char)*
 								(strlen (value) + strlen (name) + 1 + 1));
 			sprintf(env, "%s=%s", name, value);
 			putenv(env);
 		}
 		char* getEnv() {return getenv(name);};
 		virtual ~EnvironmentVariable() { free(name);};
 	private:
 		char* name;
 		static bool setEnvironmentVariableOneTime;
 	};
 
 
 int main(int argc, char** argv)
 {
 char * str = 0;
 try 
 {
 	if (argc < 4) 
 	{
 		cout << "Usage: env_mem_leak <environment variable name> ";
 		cout << "<iterations> <bifurcations>" << endl;
 		cout << "Where iterations is the number of times to set the variable ";
 		cout << "and bifrucations is the number of changes in the length of "; 
 		cout << "the string that is put into the environment variable" << endl;
 	}
 	
 	EnvironmentVariable myenv(argv[1]);
 	int iterations = atoi(argv[2]);
 	int bifurcations = atoi(argv[3]);
 	str = (char*) malloc(sizeof(char)*(bifurcations+1));
 
 	for (int i=0; i < iterations; i++)
 	{
 		memset(str, 'A', i % bifurcations);
 		str[(i % bifurcations) + 1]='\0';
 		myenv.setEnv(str);
 			////switch these to see the memory leak problem in purify!!!!!!!!!!
 		//myenv.setEnvWithLeak(str);
 		cout << myenv.getEnv() << endl;
 
 	}
 
 } 
 catch(Exception& e) 
 {
 	cout << endl << e.getErrorMessage() << endl;
 };
 if (str) free(str);
 return 0;
 }
 
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: gnats-admin->freebsd-bugs 
Responsible-Changed-By: asmodai 
Responsible-Changed-When: Sat May 13 03:59:13 PDT 2000 
Responsible-Changed-Why:  
Misfiled. 

Futhermore, see PR 18515 
State-Changed-From-To: open->closed 
State-Changed-By: phk 
State-Changed-When: Sat Jun 2 02:00:28 PDT 2001 
State-Changed-Why:  
Due to bad API design, putenv(3) is a memory leaker. 
It's even documented in the man-page. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=18519 
>Unformatted:
