ENV leaks on win32 (was Re: Comments on ENV patch sought)
Hans Mulder [Thu, 29 May 1997 08:30:44 +0000 (20:30 +1200)]
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 <pvhp@forte.com>

embed.h
global.sym
mg.c
perl.h
proto.h
t/op/magic.t

diff --git a/embed.h b/embed.h
index 0ad53a7..3c30106 100644 (file)
--- a/embed.h
+++ b/embed.h
 #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
index 50f8c53..233d4f4 100644 (file)
@@ -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 (file)
--- 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 (file)
--- 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 (file)
--- 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));
index c2be2e5..89634a7 100755 (executable)
@@ -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";
+}