develooper Front page | perl.perl5.porters | Postings from July 2012

Forcing strings in %ENV (was Re: [perl.git] branch blead, updated.v5.17.2-11-g1203306)

Thread Next
From:
Nicholas Clark
Date:
July 25, 2012 04:10
Subject:
Forcing strings in %ENV (was Re: [perl.git] branch blead, updated.v5.17.2-11-g1203306)
Message ID:
20120725111013.GA57082@plum.flirble.org
On Tue, Jul 24, 2012 at 09:39:53AM +0200, Chip Salzenberg wrote:
> In perl.git, the branch blead has been updated
> 
> <http://perl5.git.perl.org/perl.git/commitdiff/1203306491d341ed2f463fbd53a687cff1675d65?hp=a9844598bfc0b23a08d80e539ba4e03fbe392971>
> 
> - Log -----------------------------------------------------------------
> commit 1203306491d341ed2f463fbd53a687cff1675d65
> Author: Chip Salzenberg <chip@pobox.com>
> Date:   Tue Jul 24 00:39:46 2012 -0700
> 
>     ensure that the env var SV after C<{FOO}='x'> is PV only

> +    if (SvOK(sv)) {
> +	s = SvPV_const(sv,len);
> +	SvPOK_only(sv); /* environment variables are strings, period */
> +    }
> +    my_setenv(key, s); /* does the deed */
> +

Doing SvPOK_only() doesn't work in all cases - it's causing assertion
failures on references and globs. I think it needs to be SvPV_force() - ie
the appended patch.

However, even then I'm not sure if things are perfect. Why does undef get
special casing?

$ ./perl -wle '$ENV{a} = undef; print exists $ENV{a} ? "e" : "."; print defined $ENV{a} ? "d" : "."'
e
.

[ie no warnings, and not forced to the empty string]


Also, doing this, I found something I didn't know. This is OS X:

$ ./env zero foo one =bar two ==baz
getenv("zero") is "foo"
getenv("one") is "bar"
getenv("two") is "=baz"

FreeBSD and Linux both give

$ ./env zero foo one =bar two ==baz
getenv("zero") is "foo"
getenv("one") is "=bar"
getenv("two") is "==baz"

(test program attached)

All do this:

$ ./env bad= foo
setenv: Invalid argument

which means that part of the OS X man page is wrong:

     int
     setenv(const char *name, const char *value, int overwrite);

     int
     unsetenv(const char *name);

DESCRIPTION
     These functions set, unset and fetch environment variables from the host
     environment list.  For compatibility with differing environment conven-
     tions, the given arguments name and value may be appended and prepended,
     respectively, with an equal sign ``=''.

Great.

Nicholas Clark

diff --git a/ext/Devel-Peek/t/Peek.t b/ext/Devel-Peek/t/Peek.t
index 1d0de0d..0b8f938 100644
--- a/ext/Devel-Peek/t/Peek.t
+++ b/ext/Devel-Peek/t/Peek.t
@@ -543,7 +543,7 @@ do_test('scalar with pos magic',
 # environment variables may be invisibly case-forced, hence the (?i:PATH)
 # C<scalar(@ARGV)> is turned into an IV on VMS hence the (?:IV)?
 # Perl 5.18 ensures all env vars end up as strings only, hence the (?:,pIOK)?
-# Perl 5.18 ensures even magic vars have public OK, hence the (?:,POK)?
+# Perl 5.18 ensures even magic vars have public OK, hence the (?:,IOK,POK)?
 # VMS is setting FAKE and READONLY flags.  What VMS uses for storing
 # ENV hashes is also not always null terminated.
 #
@@ -551,7 +551,7 @@ do_test('tainted value in %ENV',
         $ENV{PATH}=@ARGV,  # scalar(@ARGV) is a handy known tainted value
 'SV = PVMG\\($ADDR\\) at $ADDR
   REFCNT = 1
-  FLAGS = \\(GMG,SMG,RMG(?:,POK)?(?:,pIOK)?,pPOK\\)
+  FLAGS = \\(GMG,SMG,RMG(?:,IOK,POK)?(?:,pIOK)?,pPOK\\)
   IV = 0
   NV = 0
   PV = $ADDR "0"\\\0
diff --git a/mg.c b/mg.c
index 2705109..89c628d 100644
--- a/mg.c
+++ b/mg.c
@@ -1170,8 +1170,8 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
     PERL_ARGS_ASSERT_MAGIC_SETENV;
 
     if (SvOK(sv)) {
-	s = SvPV_const(sv,len);
-	SvPOK_only(sv); /* environment variables are strings, period */
+        /* environment variables are strings, period */
+	s = SvPV_force(sv,len);
     }
     my_setenv(key, s); /* does the deed */
 
diff --git a/t/op/magic.t b/t/op/magic.t
index 643eeb6..105e61d 100644
--- a/t/op/magic.t
+++ b/t/op/magic.t
@@ -5,7 +5,7 @@ BEGIN {
     chdir 't' if -d 't';
     @INC = '../lib';
     require './test.pl';
-    plan (tests => 156);
+    plan (tests => 160);
 }
 
 # Test that defined() returns true for magic variables created on the fly,
@@ -584,7 +584,7 @@ SKIP: {
 # ^^^^^^^^^ New tests go here ^^^^^^^^^
 
 SKIP: {
-    skip("%ENV manipulations fail or aren't safe on $^O", 4)
+    skip("%ENV manipulations fail or aren't safe on $^O", 8)
 	if $Is_VMS || $Is_Dos;
 
  SKIP: {
@@ -649,6 +649,14 @@ SKIP: {
 	       || ($^O eq 'freebsd' && $ps =~ m/^(?:perl: )?x(?: \(perl\))?$/),
 		       'altering $0 is effective (testing with `ps`)');
 	}
+
+	$ENV{foo} = [];
+	is(ref $ENV{foo}, '', '%ENV forces values to plain strings');
+	like($ENV{foo}, qr/\AARRAY\(0x[0-9a-f]+\)\z/,
+	     '%ENV forces values to plain strings');
+	$ENV{foo} = *STDOUT;
+	is(ref \$ENV{foo}, 'SCALAR', '%ENV forces globs to plain strings');
+	is($ENV{foo}, '*main::STDOUT', '%ENV forces globs to plain strings');
 }
 
 # test case-insignificance of %ENV (these tests must be enabled only

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About