From: Hans Mulder Date: Thu, 29 May 1997 08:30:44 +0000 (+1200) Subject: ENV leaks on win32 (was Re: Comments on ENV patch sought) X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=66b1d5575fd5eb6242bac2e9a08b163be8b1b960;p=p5sagit%2Fp5-mst-13.2.git ENV leaks on win32 (was Re: Comments on ENV patch sought) Subject: [PATCH] for NETaa13787: %ENV=(); doesn't clear the environment Perl maintains two representations of the environment: (A) a hash named %ENV, used by the perl script (B) a char** named environ, which is passed to child processes Obviously, the intent is to keep tho two in sync. This fails in two situations: (1) A list assignment to %ENV clears (A) but not (B); (2) Assigning to $0 has the side effect of deleting the key NoNeSuCh form (B) but not from (A). $ perl -e '%ENV=(); print "home\n" if exists $ENV{HOME}; exec "echo \$HOME";' /Users/hansm $ perl -e '$ENV{NoNeSuCh} = "foo"; $0 = "bar"; exec "echo \$NoNeSuCh";' $ perl -e '$ENV{NoNeSuCh} = "foo"; exec "echo \$NoNeSuCh";' foo $ I've complained about rpoblem (1) before; and Larry assigned it bug ID NETaa13787 when he entered it into DDTS. The patch below attempts to remedy both problems, at least on Unix platforms. I don't know how to handle the environment on VMS and WIN32; my code simply calls DIE('unimplemented"), which is honest but won't make users on those plaforms happy. p5p-msgid: 199705292240.AAA01135@mail.euronet.nl Signed-off-by: Peter Prymmer --- diff --git a/embed.h b/embed.h index 0ad53a7..3c30106 100644 --- a/embed.h +++ b/embed.h @@ -308,6 +308,7 @@ #define lshift_ass_amg Perl_lshift_ass_amg #define lt_amg Perl_lt_amg #define magic_clearenv Perl_magic_clearenv +#define magic_clear_all_env Perl_magic_clear_all_env #define magic_clearpack Perl_magic_clearpack #define magic_clearsig Perl_magic_clearsig #define magic_existspack Perl_magic_existspack diff --git a/global.sym b/global.sym index 50f8c53..233d4f4 100644 --- a/global.sym +++ b/global.sym @@ -494,6 +494,7 @@ listkids localize looks_like_number magic_clearenv +magic_clearenviron magic_clearpack magic_clearsig magic_existspack diff --git a/mg.c b/mg.c index cab0e59..3d1e1ee 100644 --- a/mg.c +++ b/mg.c @@ -654,6 +654,25 @@ MAGIC* mg; } int +magic_clear_all_env() +{ +#if defined(VMS) || defined(WIN32) + DIE("'%ENV = @list;' is not implemented on this machine"); +#else + I32 i; + + if (environ == origenviron) + New(901, environ, 1, char*); + else + for (i = 0; environ[i]; i++) + Safefree(environ[i]); + environ[0] = Nullch; + + return 0; +#endif +} + +int magic_getsig(sv,mg) SV* sv; MAGIC* mg; @@ -1574,7 +1593,7 @@ MAGIC* mg; } /* can grab env area too? */ if (origenviron && origenviron[0] == s + 1) { - my_setenv("NoNeSuCh", Nullch); + my_setenv("NoNe SuCh", Nullch); /* force copy of environment */ for (i = 0; origenviron[i]; i++) if (origenviron[i] == s + 1) diff --git a/perl.h b/perl.h index 77ffb53..6b2e66d 100644 --- a/perl.h +++ b/perl.h @@ -1927,7 +1927,8 @@ EXT MGVTBL vtbl_sv = {magic_get, magic_set, magic_len, 0, 0}; -EXT MGVTBL vtbl_env = {0, 0, 0, 0, 0}; +EXT MGVTBL vtbl_env = {0, 0, 0, magic_clear_all_env, + 0}; EXT MGVTBL vtbl_envelem = {0, magic_setenv, 0, magic_clearenv, 0}; diff --git a/proto.h b/proto.h index 654e51b..9cff740 100644 --- a/proto.h +++ b/proto.h @@ -183,6 +183,7 @@ OP* listkids _((OP* o)); OP* localize _((OP* arg, I32 lexical)); I32 looks_like_number _((SV* sv)); int magic_clearenv _((SV* sv, MAGIC* mg)); +int magic_clear_all_env _((void)); int magic_clearpack _((SV* sv, MAGIC* mg)); int magic_clearsig _((SV* sv, MAGIC* mg)); int magic_existspack _((SV* sv, MAGIC* mg)); diff --git a/t/op/magic.t b/t/op/magic.t index c2be2e5..89634a7 100755 --- a/t/op/magic.t +++ b/t/op/magic.t @@ -22,7 +22,7 @@ sub ok { $Is_MSWin32 = ($^O eq 'MSWin32'); $PERL = ($Is_MSWin32 ? '.\perl' : './perl'); -print "1..28\n"; +print "1..30\n"; eval '$ENV{"foo"} = "hi there";'; # check that ENV is inited inside eval if ($Is_MSWin32) { ok 1, `cmd /x /c set foo` eq "foo=hi there\n"; } @@ -142,3 +142,16 @@ EOF ok 26, $] >= 5.00319, $]; ok 27, $^O; ok 28, $^T > 850000000, $^T; + +if ($Is_MSWin32) { + ok 29, 1; + ok 30, 1; +} +else { + %ENV = (); + ok 29, `echo \$foo` eq "\n"; + + $ENV{NoNeSuCh} = "foo"; + $0 = "bar"; + ok 30, `echo \$NoNeSuCh` eq "foo\n"; +}