From 44e8c0a01c0a4104585a07493094db8366e7ccc8 Mon Sep 17 00:00:00 2001 From: hobbs Date: Wed, 5 Oct 2005 08:03:35 +0000 Subject: * tests/env.test (env-6.1): * win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1 * generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add USE_PUTENV_FOR_UNSET to existing USE_PUTENV define to account for various systems that have putenv(), but can't unset env vars with it. Note difference between Windows and Linux for actually unsetting the env var (use of '='). Correct the resizing of the environ array. We assume that we are in full ownership, but that's not correct.[Bug 979640] --- ChangeLog | 12 ++++++++++++ generic/tclEnv.c | 34 +++++++++++++++++++++++++++------- tests/env.test | 9 ++++++++- win/tclWinPort.h | 5 +++-- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1b5894..866e14d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-10-05 Jeff Hobbs + + * tests/env.test (env-6.1): + * win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1 + * generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add + USE_PUTENV_FOR_UNSET to existing USE_PUTENV define to account for + various systems that have putenv(), but can't unset env vars with + it. Note difference between Windows and Linux for actually + unsetting the env var (use of '='). + Correct the resizing of the environ array. We assume that we are + in full ownership, but that's not correct.[Bug 979640] + 2005-10-04 Jeff Hobbs * win/tclWinSerial.c (SerialSetOptionProc): free argv [Bug 1067708] diff --git a/generic/tclEnv.c b/generic/tclEnv.c index 287a3a8..2aa927b 100644 --- a/generic/tclEnv.c +++ b/generic/tclEnv.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEnv.c,v 1.25 2005/07/21 14:38:31 dkf Exp $ + * RCS: @(#) $Id: tclEnv.c,v 1.26 2005/10/05 08:03:35 hobbs Exp $ */ #include "tclInt.h" @@ -25,6 +25,11 @@ static char **environCache = NULL; * strings that Tcl has allocated. */ #ifndef USE_PUTENV +static char **ourEnviron = NULL;/* Cache of the array that we allocate. + * We need to track this in case another + * subsystem swaps around the environ array + * like we do. + */ static int environSize = 0; /* Non-zero means that the environ array was * malloced and has this many total entries * allocated to it (not all may be in use at @@ -189,17 +194,22 @@ TclSetEnv(name, value) if (index == -1) { #ifndef USE_PUTENV - if ((length + 2) > environSize) { + /* + * We need to handle the case where the environment may be changed + * outside our control. environSize is only valid if the current + * environment is the one we allocated. [Bug 979640] + */ + if ((ourEnviron != environ) || ((length + 2) > environSize)) { char **newEnviron; newEnviron = (char **) ckalloc((unsigned) ((length + 5) * sizeof(char *))); memcpy((VOID *) newEnviron, (VOID *) environ, length*sizeof(char *)); - if (environSize != 0) { - ckfree((char *) environ); + if ((environSize != 0) && (ourEnviron != NULL)) { + ckfree((char *) ourEnviron); } - environ = newEnviron; + environ = ourEnviron = newEnviron; environSize = length + 5; #if defined(__APPLE__) && defined(__DYNAMIC__) { @@ -375,7 +385,7 @@ TclUnsetEnv(name) char *oldValue; int length; int index; -#ifdef USE_PUTENV +#ifdef USE_PUTENV_FOR_UNSET Tcl_DString envString; char *string; #else @@ -405,11 +415,21 @@ TclUnsetEnv(name) * interpreters or we will recurse. */ -#ifdef USE_PUTENV +#ifdef USE_PUTENV_FOR_UNSET + /* + * For those platforms that support putenv to unset, Linux indicates + * that no = should be included, and Windows requires it. + */ +#ifdef WIN32 string = ckalloc((unsigned int) length+2); memcpy((VOID *) string, (VOID *) name, (size_t) length); string[length] = '='; string[length+1] = '\0'; +#else + string = ckalloc((unsigned int) length+1); + memcpy((VOID *) string, (VOID *) name, (size_t) length); + string[length] = '\0'; +#endif Tcl_UtfToExternalDString(NULL, string, -1, &envString); string = ckrealloc(string, (unsigned) (Tcl_DStringLength(&envString)+1)); diff --git a/tests/env.test b/tests/env.test index 24dc2e3..c2bad61 100644 --- a/tests/env.test +++ b/tests/env.test @@ -11,7 +11,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: env.test,v 1.21 2005/05/24 04:44:08 das Exp $ +# RCS: @(#) $Id: env.test,v 1.22 2005/10/05 08:03:35 hobbs Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 @@ -232,6 +232,13 @@ test env-5.5 {corner cases - cannot have null entries on Windows} {win} { catch {set env()} } {1} +test env-6.1 {corner cases - add lots of env variables} {} { + set size [array size env] + for {set i 0} {$i < 100} {incr i} { + set env(BOGUS$i) $i + } + expr {[array size env] - $size} +} 100 # Restore the environment variables at the end of the test. diff --git a/win/tclWinPort.h b/win/tclWinPort.h index 1263e12..4c11208 100644 --- a/win/tclWinPort.h +++ b/win/tclWinPort.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinPort.h,v 1.44 2005/06/01 11:00:36 dkf Exp $ + * RCS: @(#) $Id: tclWinPort.h,v 1.45 2005/10/05 08:03:35 hobbs Exp $ */ #ifndef _TCLWINPORT @@ -445,7 +445,8 @@ * the C level environment in synch with the system level environment. */ -#define USE_PUTENV 1 +#define USE_PUTENV 1 +#define USE_PUTENV_FOR_UNSET 1 /* * Msvcrt's putenv() copies the string rather than takes ownership of it. -- cgit v0.12