fix occasional op/time.t failure
[p5sagit/p5-mst-13.2.git] / t / op / taint.t
index 69af31e..5337332 100755 (executable)
@@ -17,8 +17,7 @@ use Config;
 use File::Spec::Functions;
 
 BEGIN { require './test.pl'; }
-plan tests => 238;
-
+plan tests => 257;
 
 $| = 1;
 
@@ -45,6 +44,7 @@ my $Is_MSWin32  = $^O eq 'MSWin32';
 my $Is_NetWare  = $^O eq 'NetWare';
 my $Is_Dos      = $^O eq 'dos';
 my $Is_Cygwin   = $^O eq 'cygwin';
+my $Is_OpenBSD  = $^O eq 'openbsd';
 my $Invoke_Perl = $Is_VMS      ? 'MCR Sys$Disk:[]Perl.' :
                   $Is_MSWin32  ? '.\perl'               :
                   $Is_MacOS    ? ':perl'                :
@@ -134,6 +134,23 @@ my $TEST = catfile(curdir(), 'TEST');
 {
     $ENV{'DCL$PATH'} = '' if $Is_VMS;
 
+    if ($Is_MSWin32 && $Config{ccname} =~ /bcc32/ && ! -f 'cc3250mt.dll') {
+       my $bcc_dir;
+       foreach my $dir (split /$Config{path_sep}/, $ENV{PATH}) {
+           if (-f "$dir/cc3250mt.dll") {
+               $bcc_dir = $dir and last;
+           }
+       }
+       if (defined $bcc_dir) {
+           require File::Copy;
+           File::Copy::copy("$bcc_dir/cc3250mt.dll", '.') or
+               die "$0: failed to copy cc3250mt.dll: $!\n";
+           eval q{
+               END { unlink "cc3250mt.dll" }
+           };
+       }
+    }
+
     $ENV{PATH} = '';
     delete @ENV{@MoreEnv};
     $ENV{TERM} = 'dumb';
@@ -205,7 +222,7 @@ my $TEST = catfile(curdir(), 'TEST');
        test $@ =~ /^Insecure \$ENV{DCL\$PATH}/, $@;
        SKIP: {
             skip q[can't find world-writeable directory to test DCL$PATH], 2
-              if $tmp;
+              unless $tmp;
 
            $ENV{'DCL$PATH'} = $tmp;
            test eval { `$echo 1` } eq '';
@@ -1089,3 +1106,127 @@ TERNARY_CONDITIONALS: {
         test not any_tainted @bar;
     }
 }
+
+# at scope exit, a restored localised value should have its old
+# taint status, not the taint status of the current statement
+
+{
+    our $x99 = $^X;
+    test tainted $x99;
+
+    $x99 = '';
+    test not tainted $x99;
+
+    my $c = do { local $x99; $^X };
+    test not tainted $x99;
+}
+{
+    our $x99 = $^X;
+    test tainted $x99;
+
+    my $c = do { local $x99; '' };
+    test tainted $x99;
+}
+
+# an mg_get of a tainted value during localization shouldn't taint the
+# statement
+
+{
+    eval { local $0, eval '1' };
+    test $@ eq '';
+}
+
+# [perl #8262] //g loops infinitely on tainted data
+
+{
+    my @a;
+    local $::TODO = 1;
+    $a[0] = $^X;
+    my $i = 0;
+    while($a[0]=~ m/(.)/g ) {
+       last if $i++ > 10000;
+    }
+    cmp_ok $i, '<', 10000, "infinite m//g";
+}
+
+SKIP:
+{
+    my $got_dualvar;
+    eval 'use Scalar::Util "dualvar"; $got_dualvar++';
+    skip "No Scalar::Util::dualvar" unless $got_dualvar;
+    my $a = Scalar::Util::dualvar(3, $^X);
+    my $b = $a + 5;
+    is ($b, 8, "Arithmetic on tainted dualvars works");
+}
+
+# opening '|-' should not trigger $ENV{PATH} check
+
+{
+    SKIP: {
+       skip "fork() is not available", 3 unless $Config{'d_fork'};
+       skip "opening |- is not stable on threaded OpenBSD with taint", 3
+            if $Config{useithreads} && $Is_OpenBSD;
+
+       $ENV{'PATH'} = $TAINT;
+       local $SIG{'PIPE'} = 'IGNORE';
+       eval {
+           my $pid = open my $pipe, '|-';
+           if (!defined $pid) {
+               die "open failed: $!";
+           }
+           if (!$pid) {
+               kill 'KILL', $$;        # child suicide
+           }
+           close $pipe;
+       };
+       test $@ !~ /Insecure \$ENV/, 'fork triggers %ENV check';
+       test $@ eq '',               'pipe/fork/open/close failed';
+       eval {
+           open my $pipe, "|$Invoke_Perl -e 1";
+           close $pipe;
+       };
+       test $@ =~ /Insecure \$ENV/, 'popen neglects %ENV check';
+    }
+}
+
+{
+    package AUTOLOAD_TAINT;
+    sub AUTOLOAD {
+        our $AUTOLOAD;
+        return if $AUTOLOAD =~ /DESTROY/;
+        if ($AUTOLOAD =~ /untainted/) {
+            main::ok(!main::tainted($AUTOLOAD), '$AUTOLOAD can be untainted');
+        } else {
+            main::ok(main::tainted($AUTOLOAD), '$AUTOLOAD can be tainted');
+        }
+    }
+
+    package main;
+    my $o = bless [], 'AUTOLOAD_TAINT';
+    $o->$TAINT;
+    $o->untainted;
+}
+
+{
+    # tests for tainted format in s?printf
+    eval { printf($TAINT . "# %s\n", "foo") };
+    like($@, qr/^Insecure dependency in printf/, q/printf doesn't like tainted formats/);
+    eval { printf("# %s\n", $TAINT . "foo") };
+    ok(!$@, q/printf accepts other tainted args/);
+    eval { sprintf($TAINT . "# %s\n", "foo") };
+    like($@, qr/^Insecure dependency in sprintf/, q/sprintf doesn't like tainted formats/);
+    eval { sprintf("# %s\n", $TAINT . "foo") };
+    ok(!$@, q/sprintf accepts other tainted args/);
+}
+
+{
+    # 40708
+    my $n  = 7e9;
+    8e9 - $n;
+
+    my $val = $n;
+    is ($val, '7000000000', 'Assignment to untainted variable');
+    $val = $TAINT;
+    $val = $n;
+    is ($val, '7000000000', 'Assignment to tainted variable');
+}