This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate mainline
[perl5.git] / t / op / taint.t
1 #!./perl -T
2 #
3 # Taint tests by Tom Phoenix <rootbeer@teleport.com>.
4 #
5 # I don't claim to know all about tainting. If anyone sees
6 # tests that I've missed here, please add them. But this is
7 # better than having no tests at all, right?
8 #
9
10 BEGIN {
11     chdir 't' if -d 't';
12     @INC = '../lib';
13 }
14
15 use strict;
16 use Config;
17
18 my $test = 177;
19 sub ok {
20     my($ok, $name) = @_;
21
22     # You have to do it this way or VMS will get confused.
23     print $ok ? "ok $test - $name\n" : "not ok $test - $name\n";
24
25     printf "# Failed test at line %d\n", (caller)[2] unless $ok;
26
27     $test++;
28     return $ok;
29 }
30
31
32 $| = 1;
33
34 # We do not want the whole taint.t to fail
35 # just because Errno possibly failing.
36 eval { require Errno; import Errno };
37
38 use vars qw($ipcsysv); # did we manage to load IPC::SysV?
39
40 BEGIN {
41   if ($^O eq 'VMS' && !defined($Config{d_setenv})) {
42       $ENV{PATH} = $ENV{PATH};
43       $ENV{TERM} = $ENV{TERM} ne ''? $ENV{TERM} : 'dummy';
44   }
45   if ($Config{'extensions'} =~ /\bIPC\/SysV\b/
46       && ($Config{d_shm} || $Config{d_msg})) {
47       eval { require IPC::SysV };
48       unless ($@) {
49           $ipcsysv++;
50           IPC::SysV->import(qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU));
51       }
52   }
53 }
54
55 my $Is_VMS = $^O eq 'VMS';
56 my $Is_MSWin32 = $^O eq 'MSWin32';
57 my $Is_NetWare = $^O eq 'NetWare';
58 my $Is_Dos = $^O eq 'dos';
59 my $Is_Cygwin = $^O eq 'cygwin';
60 my $Invoke_Perl = $Is_VMS ? 'MCR Sys$Disk:[]Perl.' :
61                   ($Is_MSWin32 ? '.\perl' :
62                   ($Is_NetWare ? 'perl' : './perl'));
63 my @MoreEnv = qw/IFS CDPATH ENV BASH_ENV/;
64
65 if ($Is_VMS) {
66     my (%old, $x);
67     for $x ('DCL$PATH', @MoreEnv) {
68         ($old{$x}) = $ENV{$x} =~ /^(.*)$/ if exists $ENV{$x};
69     }
70     eval <<EndOfCleanup;
71         END {
72             \$ENV{PATH} = '' if $Config{d_setenv};
73             warn "# Note: logical name 'PATH' may have been deleted\n";
74             \@ENV{keys %old} = values %old;
75         }
76 EndOfCleanup
77 }
78
79 # Sources of taint:
80 #   The empty tainted value, for tainting strings
81 my $TAINT = substr($^X, 0, 0);
82 #   A tainted zero, useful for tainting numbers
83 my $TAINT0 = 0 + $TAINT;
84
85 # This taints each argument passed. All must be lvalues.
86 # Side effect: It also stringifies them. :-(
87 sub taint_these (@) {
88     for (@_) { $_ .= $TAINT }
89 }
90
91 # How to identify taint when you see it
92 sub any_tainted (@) {
93     not eval { join("",@_), kill 0; 1 };
94 }
95 sub tainted ($) {
96     any_tainted @_;
97 }
98 sub all_tainted (@) {
99     for (@_) { return 0 unless tainted $_ }
100     1;
101 }
102
103 sub test ($$;$) {
104     my($serial, $boolean, $diag) = @_;
105     if ($boolean) {
106         print "ok $serial\n";
107     } else {
108         print "not ok $serial\n";
109         for (split m/^/m, $diag) {
110             print "# $_";
111         }
112         print "\n" unless
113             $diag eq ''
114             or substr($diag, -1) eq "\n";
115     }
116 }
117
118 # We need an external program to call.
119 my $ECHO = ($Is_MSWin32 ? ".\\echo$$" : ($Is_NetWare ? "echo$$" : "./echo$$"));
120 END { unlink $ECHO }
121 open PROG, "> $ECHO" or die "Can't create $ECHO: $!";
122 print PROG 'print "@ARGV\n"', "\n";
123 close PROG;
124 my $echo = "$Invoke_Perl $ECHO";
125
126 print "1..183\n";
127
128 # First, let's make sure that Perl is checking the dangerous
129 # environment variables. Maybe they aren't set yet, so we'll
130 # taint them ourselves.
131 {
132     $ENV{'DCL$PATH'} = '' if $Is_VMS;
133
134     $ENV{PATH} = '';
135     delete @ENV{@MoreEnv};
136     $ENV{TERM} = 'dumb';
137
138     if ($Is_Cygwin && ! -f 'cygwin1.dll') {
139         system("/usr/bin/cp /usr/bin/cygwin1.dll .") &&
140             die "$0: failed to cp cygwin1.dll: $!\n";
141         END { unlink "cygwin1.dll" } # yes, done for all platforms...
142     }
143
144     test 1, eval { `$echo 1` } eq "1\n";
145
146     if ($Is_MSWin32 || $Is_NetWare || $Is_VMS || $Is_Dos) {
147         print "# Environment tainting tests skipped\n";
148         for (2..5) { print "ok $_\n" }
149     }
150     else {
151         my @vars = ('PATH', @MoreEnv);
152         while (my $v = $vars[0]) {
153             local $ENV{$v} = $TAINT;
154             last if eval { `$echo 1` };
155             last unless $@ =~ /^Insecure \$ENV{$v}/;
156             shift @vars;
157         }
158         test 2, !@vars, "\$$vars[0]";
159
160         # tainted $TERM is unsafe only if it contains metachars
161         local $ENV{TERM};
162         $ENV{TERM} = 'e=mc2';
163         test 3, eval { `$echo 1` } eq "1\n";
164         $ENV{TERM} = 'e=mc2' . $TAINT;
165         test 4, eval { `$echo 1` } eq '';
166         test 5, $@ =~ /^Insecure \$ENV{TERM}/, $@;
167     }
168
169     my $tmp;
170     if ($^O eq 'os2' || $^O eq 'amigaos' || $Is_MSWin32 || $Is_NetWare || $Is_Dos) {
171         print "# all directories are writeable\n";
172     }
173     else {
174         $tmp = (grep { defined and -d and (stat _)[2] & 2 }
175                      qw(sys$scratch /tmp /var/tmp /usr/tmp),
176                      @ENV{qw(TMP TEMP)})[0]
177             or print "# can't find world-writeable directory to test PATH\n";
178     }
179
180     if ($tmp) {
181         local $ENV{PATH} = $tmp;
182         test 6, eval { `$echo 1` } eq '';
183         test 7, $@ =~ /^Insecure directory in \$ENV{PATH}/, $@;
184     }
185     else {
186         for (6..7) { print "ok $_ # Skipped: all directories are writeable\n" }
187     }
188
189     if ($Is_VMS) {
190         $ENV{'DCL$PATH'} = $TAINT;
191         test 8,  eval { `$echo 1` } eq '';
192         test 9, $@ =~ /^Insecure \$ENV{DCL\$PATH}/, $@;
193         if ($tmp) {
194             $ENV{'DCL$PATH'} = $tmp;
195             test 10, eval { `$echo 1` } eq '';
196             test 11, $@ =~ /^Insecure directory in \$ENV{DCL\$PATH}/, $@;
197         }
198         else {
199             for (10..11) { print "ok $_ # Skipped: can't find world-writeable directory to test DCL\$PATH\n" }
200         }
201         $ENV{'DCL$PATH'} = '';
202     }
203     else {
204         for (8..11) { print "ok $_ # Skipped: This is not VMS\n"; }
205     }
206 }
207
208 # Let's see that we can taint and untaint as needed.
209 {
210     my $foo = $TAINT;
211     test 12, tainted $foo;
212
213     # That was a sanity check. If it failed, stop the insanity!
214     die "Taint checks don't seem to be enabled" unless tainted $foo;
215
216     $foo = "foo";
217     test 13, not tainted $foo;
218
219     taint_these($foo);
220     test 14, tainted $foo;
221
222     my @list = 1..10;
223     test 15, not any_tainted @list;
224     taint_these @list[1,3,5,7,9];
225     test 16, any_tainted @list;
226     test 17, all_tainted @list[1,3,5,7,9];
227     test 18, not any_tainted @list[0,2,4,6,8];
228
229     ($foo) = $foo =~ /(.+)/;
230     test 19, not tainted $foo;
231
232     $foo = $1 if ('bar' . $TAINT) =~ /(.+)/;
233     test 20, not tainted $foo;
234     test 21, $foo eq 'bar';
235
236     {
237       use re 'taint';
238
239       ($foo) = ('bar' . $TAINT) =~ /(.+)/;
240       test 22, tainted $foo;
241       test 23, $foo eq 'bar';
242
243       $foo = $1 if ('bar' . $TAINT) =~ /(.+)/;
244       test 24, tainted $foo;
245       test 25, $foo eq 'bar';
246     }
247
248     $foo = $1 if 'bar' =~ /(.+)$TAINT/;
249     test 26, tainted $foo;
250     test 27, $foo eq 'bar';
251
252     my $pi = 4 * atan2(1,1) + $TAINT0;
253     test 28, tainted $pi;
254
255     ($pi) = $pi =~ /(\d+\.\d+)/;
256     test 29, not tainted $pi;
257     test 30, sprintf("%.5f", $pi) eq '3.14159';
258 }
259
260 # How about command-line arguments? The problem is that we don't
261 # always get some, so we'll run another process with some.
262 {
263     my $arg = "./arg$$";
264     open PROG, "> $arg" or die "Can't create $arg: $!";
265     print PROG q{
266         eval { join('', @ARGV), kill 0 };
267         exit 0 if $@ =~ /^Insecure dependency/;
268         print "# Oops: \$@ was [$@]\n";
269         exit 1;
270     };
271     close PROG;
272     print `$Invoke_Perl "-T" $arg and some suspect arguments`;
273     test 31, !$?, "Exited with status $?";
274     unlink $arg;
275 }
276
277 # Reading from a file should be tainted
278 {
279     my $file = './TEST';
280     test 32, open(FILE, $file), "Couldn't open '$file': $!";
281
282     my $block;
283     sysread(FILE, $block, 100);
284     my $line = <FILE>;
285     close FILE;
286     test 33, tainted $block;
287     test 34, tainted $line;
288 }
289
290 # Globs should be forbidden, except under VMS,
291 #   which doesn't spawn an external program.
292 if (1  # built-in glob
293     or $Is_VMS) {
294     for (35..36) { print "ok $_\n"; }
295 }
296 else {
297     my @globs = eval { <*> };
298     test 35, @globs == 0 && $@ =~ /^Insecure dependency/;
299
300     @globs = eval { glob '*' };
301     test 36, @globs == 0 && $@ =~ /^Insecure dependency/;
302 }
303
304 # Output of commands should be tainted
305 {
306     my $foo = `$echo abc`;
307     test 37, tainted $foo;
308 }
309
310 # Certain system variables should be tainted
311 {
312     test 38, all_tainted $^X, $0;
313 }
314
315 # Results of matching should all be untainted
316 {
317     my $foo = "abcdefghi" . $TAINT;
318     test 39, tainted $foo;
319
320     $foo =~ /def/;
321     test 40, not any_tainted $`, $&, $';
322
323     $foo =~ /(...)(...)(...)/;
324     test 41, not any_tainted $1, $2, $3, $+;
325
326     my @bar = $foo =~ /(...)(...)(...)/;
327     test 42, not any_tainted @bar;
328
329     test 43, tainted $foo;      # $foo should still be tainted!
330     test 44, $foo eq "abcdefghi";
331 }
332
333 # Operations which affect files can't use tainted data.
334 {
335     test 45, eval { chmod 0, $TAINT } eq '', 'chmod';
336     test 46, $@ =~ /^Insecure dependency/, $@;
337
338     # There is no feature test in $Config{} for truncate,
339     #   so we allow for the possibility that it's missing.
340     test 47, eval { truncate 'NoSuChFiLe', $TAINT0 } eq '', 'truncate';
341     test 48, $@ =~ /^(?:Insecure dependency|truncate not implemented)/, $@;
342
343     test 49, eval { rename '', $TAINT } eq '', 'rename';
344     test 50, $@ =~ /^Insecure dependency/, $@;
345
346     test 51, eval { unlink $TAINT } eq '', 'unlink';
347     test 52, $@ =~ /^Insecure dependency/, $@;
348
349     test 53, eval { utime $TAINT } eq '', 'utime';
350     test 54, $@ =~ /^Insecure dependency/, $@;
351
352     if ($Config{d_chown}) {
353         test 55, eval { chown -1, -1, $TAINT } eq '', 'chown';
354         test 56, $@ =~ /^Insecure dependency/, $@;
355     }
356     else {
357         for (55..56) { print "ok $_ # Skipped: chown() is not available\n" }
358     }
359
360     if ($Config{d_link}) {
361         test 57, eval { link $TAINT, '' } eq '', 'link';
362         test 58, $@ =~ /^Insecure dependency/, $@;
363     }
364     else {
365         for (57..58) { print "ok $_ # Skipped: link() is not available\n" }
366     }
367
368     if ($Config{d_symlink}) {
369         test 59, eval { symlink $TAINT, '' } eq '', 'symlink';
370         test 60, $@ =~ /^Insecure dependency/, $@;
371     }
372     else {
373         for (59..60) { print "ok $_ # Skipped: symlink() is not available\n" }
374     }
375 }
376
377 # Operations which affect directories can't use tainted data.
378 {
379     test 61, eval { mkdir $TAINT0, $TAINT } eq '', 'mkdir';
380     test 62, $@ =~ /^Insecure dependency/, $@;
381
382     test 63, eval { rmdir $TAINT } eq '', 'rmdir';
383     test 64, $@ =~ /^Insecure dependency/, $@;
384
385     test 65, eval { chdir $TAINT } eq '', 'chdir';
386     test 66, $@ =~ /^Insecure dependency/, $@;
387
388     if ($Config{d_chroot}) {
389         test 67, eval { chroot $TAINT } eq '', 'chroot';
390         test 68, $@ =~ /^Insecure dependency/, $@;
391     }
392     else {
393         for (67..68) { print "ok $_ # Skipped: chroot() is not available\n" }
394     }
395 }
396
397 # Some operations using files can't use tainted data.
398 {
399     my $foo = "imaginary library" . $TAINT;
400     test 69, eval { require $foo } eq '', 'require';
401     test 70, $@ =~ /^Insecure dependency/, $@;
402
403     my $filename = "./taintB$$";        # NB: $filename isn't tainted!
404     END { unlink $filename if defined $filename }
405     $foo = $filename . $TAINT;
406     unlink $filename;   # in any case
407
408     test 71, eval { open FOO, $foo } eq '', 'open for read';
409     test 72, $@ eq '', $@;              # NB: This should be allowed
410
411     # Try first new style but allow also old style.
412     test 73, $!{ENOENT} ||
413         $! == 2 || # File not found
414         ($Is_Dos && $! == 22) ||
415         ($^O eq 'mint' && $! == 33);
416
417     test 74, eval { open FOO, "> $foo" } eq '', 'open for write';
418     test 75, $@ =~ /^Insecure dependency/, $@;
419 }
420
421 # Commands to the system can't use tainted data
422 {
423     my $foo = $TAINT;
424
425     if ($^O eq 'amigaos') {
426         for (76..79) { print "ok $_ # Skipped: open('|') is not available\n" }
427     }
428     else {
429         test 76, eval { open FOO, "| x$foo" } eq '', 'popen to';
430         test 77, $@ =~ /^Insecure dependency/, $@;
431
432         test 78, eval { open FOO, "x$foo |" } eq '', 'popen from';
433         test 79, $@ =~ /^Insecure dependency/, $@;
434     }
435
436     test 80, eval { exec $TAINT } eq '', 'exec';
437     test 81, $@ =~ /^Insecure dependency/, $@;
438
439     test 82, eval { system $TAINT } eq '', 'system';
440     test 83, $@ =~ /^Insecure dependency/, $@;
441
442     $foo = "*";
443     taint_these $foo;
444
445     test 84, eval { `$echo 1$foo` } eq '', 'backticks';
446     test 85, $@ =~ /^Insecure dependency/, $@;
447
448     if ($Is_VMS) { # wildcard expansion doesn't invoke shell, so is safe
449         test 86, join('', eval { glob $foo } ) ne '', 'globbing';
450         test 87, $@ eq '', $@;
451     }
452     else {
453         for (86..87) { print "ok $_ # Skipped: this is not VMS\n"; }
454     }
455 }
456
457 # Operations which affect processes can't use tainted data.
458 {
459     test 88, eval { kill 0, $TAINT } eq '', 'kill';
460     test 89, $@ =~ /^Insecure dependency/, $@;
461
462     if ($Config{d_setpgrp}) {
463         test 90, eval { setpgrp 0, $TAINT } eq '', 'setpgrp';
464         test 91, $@ =~ /^Insecure dependency/, $@;
465     }
466     else {
467         for (90..91) { print "ok $_ # Skipped: setpgrp() is not available\n" }
468     }
469
470     if ($Config{d_setprior}) {
471         test 92, eval { setpriority 0, $TAINT, $TAINT } eq '', 'setpriority';
472         test 93, $@ =~ /^Insecure dependency/, $@;
473     }
474     else {
475         for (92..93) { print "ok $_ # Skipped: setpriority() is not available\n" }
476     }
477 }
478
479 # Some miscellaneous operations can't use tainted data.
480 {
481     if ($Config{d_syscall}) {
482         test 94, eval { syscall $TAINT } eq '', 'syscall';
483         test 95, $@ =~ /^Insecure dependency/, $@;
484     }
485     else {
486         for (94..95) { print "ok $_ # Skipped: syscall() is not available\n" }
487     }
488
489     {
490         my $foo = "x" x 979;
491         taint_these $foo;
492         local *FOO;
493         my $temp = "./taintC$$";
494         END { unlink $temp }
495         test 96, open(FOO, "> $temp"), "Couldn't open $temp for write: $!";
496
497         test 97, eval { ioctl FOO, $TAINT, $foo } eq '', 'ioctl';
498         test 98, $@ =~ /^Insecure dependency/, $@;
499
500         if ($Config{d_fcntl}) {
501             test 99, eval { fcntl FOO, $TAINT, $foo } eq '', 'fcntl';
502             test 100, $@ =~ /^Insecure dependency/, $@;
503         }
504         else {
505             for (99..100) { print "ok $_ # Skipped: fcntl() is not available\n" }
506         }
507
508         close FOO;
509     }
510 }
511
512 # Some tests involving references
513 {
514     my $foo = 'abc' . $TAINT;
515     my $fooref = \$foo;
516     test 101, not tainted $fooref;
517     test 102, tainted $$fooref;
518     test 103, tainted $foo;
519 }
520
521 # Some tests involving assignment
522 {
523     my $foo = $TAINT0;
524     my $bar = $foo;
525     test 104, all_tainted $foo, $bar;
526     test 105, tainted($foo = $bar);
527     test 106, tainted($bar = $bar);
528     test 107, tainted($bar += $bar);
529     test 108, tainted($bar -= $bar);
530     test 109, tainted($bar *= $bar);
531     test 110, tainted($bar++);
532     test 111, tainted($bar /= $bar);
533     test 112, tainted($bar += 0);
534     test 113, tainted($bar -= 2);
535     test 114, tainted($bar *= -1);
536     test 115, tainted($bar /= 1);
537     test 116, tainted($bar--);
538     test 117, $bar == 0;
539 }
540
541 # Test assignment and return of lists
542 {
543     my @foo = ("A", "tainted" . $TAINT, "B");
544     test 118, not tainted $foo[0];
545     test 119,     tainted $foo[1];
546     test 120, not tainted $foo[2];
547     my @bar = @foo;
548     test 121, not tainted $bar[0];
549     test 122,     tainted $bar[1];
550     test 123, not tainted $bar[2];
551     my @baz = eval { "A", "tainted" . $TAINT, "B" };
552     test 124, not tainted $baz[0];
553     test 125,     tainted $baz[1];
554     test 126, not tainted $baz[2];
555     my @plugh = eval q[ "A", "tainted" . $TAINT, "B" ];
556     test 127, not tainted $plugh[0];
557     test 128,     tainted $plugh[1];
558     test 129, not tainted $plugh[2];
559     my $nautilus = sub { "A", "tainted" . $TAINT, "B" };
560     test 130, not tainted ((&$nautilus)[0]);
561     test 131,     tainted ((&$nautilus)[1]);
562     test 132, not tainted ((&$nautilus)[2]);
563     my @xyzzy = &$nautilus;
564     test 133, not tainted $xyzzy[0];
565     test 134,     tainted $xyzzy[1];
566     test 135, not tainted $xyzzy[2];
567     my $red_october = sub { return "A", "tainted" . $TAINT, "B" };
568     test 136, not tainted ((&$red_october)[0]);
569     test 137,     tainted ((&$red_october)[1]);
570     test 138, not tainted ((&$red_october)[2]);
571     my @corge = &$red_october;
572     test 139, not tainted $corge[0];
573     test 140,     tainted $corge[1];
574     test 141, not tainted $corge[2];
575 }
576
577 # Test for system/library calls returning string data of dubious origin.
578 {
579     # No reliable %Config check for getpw*
580     if (eval { setpwent(); getpwent() }) {
581         setpwent();
582         my @getpwent = getpwent();
583         die "getpwent: $!\n" unless (@getpwent);
584         test 142,(    not tainted $getpwent[0]
585                   and     tainted $getpwent[1]
586                   and not tainted $getpwent[2]
587                   and not tainted $getpwent[3]
588                   and not tainted $getpwent[4]
589                   and not tainted $getpwent[5]
590                   and     tainted $getpwent[6]          # ge?cos
591                   and not tainted $getpwent[7]
592                   and     tainted $getpwent[8]);        # shell
593         endpwent();
594     } else {
595         for (142) { print "ok $_ # Skipped: getpwent() is not available\n" }
596     }
597
598     if ($Config{d_readdir}) { # pretty hard to imagine not
599         local(*D);
600         opendir(D, "op") or die "opendir: $!\n";
601         my $readdir = readdir(D);
602         test 143, tainted $readdir;
603         closedir(OP);
604     } else {
605         for (143) { print "ok $_ # Skipped: readdir() is not available\n" }
606     }
607
608     if ($Config{d_readlink} && $Config{d_symlink}) {
609         my $symlink = "sl$$";
610         unlink($symlink);
611         symlink("/something/naughty", $symlink) or die "symlink: $!\n";
612         my $readlink = readlink($symlink);
613         test 144, tainted $readlink;
614         unlink($symlink);
615     } else {
616         for (144) { print "ok $_ # Skipped: readlink() or symlink() is not available\n"; }
617     }
618 }
619
620 # test bitwise ops (regression bug)
621 {
622     my $why = "y";
623     my $j = "x" | $why;
624     test 145, not tainted $j;
625     $why = $TAINT."y";
626     $j = "x" | $why;
627     test 146,     tainted $j;
628 }
629
630 # test target of substitution (regression bug)
631 {
632     my $why = $TAINT."y";
633     $why =~ s/y/z/;
634     test 147,     tainted $why;
635
636     my $z = "[z]";
637     $why =~ s/$z/zee/;
638     test 148,     tainted $why;
639
640     $why =~ s/e/'-'.$$/ge;
641     test 149,     tainted $why;
642 }
643
644 # test shmread
645 {
646     unless ($ipcsysv) {
647         print "ok 150 # skipped: no IPC::SysV\n";
648         last;
649     }
650     if ($Config{'extensions'} =~ /\bIPC\/SysV\b/ && $Config{d_shm}) {
651         no strict 'subs';
652         my $sent = "foobar";
653         my $rcvd;
654         my $size = 2000;
655         my $id = shmget(IPC_PRIVATE, $size, S_IRWXU);
656
657         if (defined $id) {
658             if (shmwrite($id, $sent, 0, 60)) {
659                 if (shmread($id, $rcvd, 0, 60)) {
660                     substr($rcvd, index($rcvd, "\0")) = '';
661                 } else {
662                     warn "# shmread failed: $!\n";
663                 }
664             } else {
665                 warn "# shmwrite failed: $!\n";
666             }
667             shmctl($id, IPC_RMID, 0) or warn "# shmctl failed: $!\n";
668         } else {
669             warn "# shmget failed: $!\n";
670         }
671
672         if ($rcvd eq $sent) {
673             test 150, tainted $rcvd;
674         } else {
675             print "ok 150 # Skipped: SysV shared memory operation failed\n";
676         }
677     } else {
678         print "ok 150 # Skipped: SysV shared memory is not available\n";
679     }
680 }
681
682 # test msgrcv
683 {
684     unless ($ipcsysv) {
685         print "ok 151 # skipped: no IPC::SysV\n";
686         last;
687     }
688     if ($Config{'extensions'} =~ /\bIPC\/SysV\b/ && $Config{d_msg}) {
689         no strict 'subs';
690         my $id = msgget(IPC_PRIVATE, IPC_CREAT | S_IRWXU);
691
692         my $sent      = "message";
693         my $type_sent = 1234;
694         my $rcvd;
695         my $type_rcvd;
696
697         if (defined $id) {
698             if (msgsnd($id, pack("l! a*", $type_sent, $sent), 0)) {
699                 if (msgrcv($id, $rcvd, 60, 0, 0)) {
700                     ($type_rcvd, $rcvd) = unpack("l! a*", $rcvd);
701                 } else {
702                     warn "# msgrcv failed\n";
703                 }
704             } else {
705                 warn "# msgsnd failed\n";
706             }
707             msgctl($id, IPC_RMID, 0) or warn "# msgctl failed: $!\n";
708         } else {
709             warn "# msgget failed\n";
710         }
711
712         if ($rcvd eq $sent && $type_sent == $type_rcvd) {
713             test 151, tainted $rcvd;
714         } else {
715             print "ok 151 # Skipped: SysV message queue operation failed\n";
716         }
717     } else {
718         print "ok 151 # Skipped: SysV message queues are not available\n";
719     }
720 }
721
722 {
723     # bug id 20001004.006
724
725     open IN, "./TEST" or warn "$0: cannot read ./TEST: $!" ;
726     local $/;
727     my $a = <IN>;
728     my $b = <IN>;
729     print "not " unless tainted($a) && tainted($b) && !defined($b);
730     print "ok 152\n";
731     close IN;
732 }
733
734 {
735     # bug id 20001004.007
736
737     open IN, "./TEST" or warn "$0: cannot read ./TEST: $!" ;
738     my $a = <IN>;
739
740     my $c = { a => 42,
741               b => $a };
742     print "not " unless !tainted($c->{a}) && tainted($c->{b});
743     print "ok 153\n";
744
745     my $d = { a => $a,
746               b => 42 };
747     print "not " unless tainted($d->{a}) && !tainted($d->{b});
748     print "ok 154\n";
749
750     my $e = { a => 42,
751               b => { c => $a, d => 42 } };
752     print "not " unless !tainted($e->{a}) &&
753                         !tainted($e->{b}) &&
754                          tainted($e->{b}->{c}) &&
755                         !tainted($e->{b}->{d});
756     print "ok 155\n";
757
758     close IN;
759 }
760
761 {
762     # bug id 20010519.003
763
764     BEGIN {
765         use vars qw($has_fcntl);
766         eval { require Fcntl; import Fcntl; };
767         unless ($@) {
768             $has_fcntl = 1;
769         }
770     }
771
772     unless ($has_fcntl) {
773         for (156..173) {
774             print "ok $_ # Skip: no Fcntl (no dynaloading?)\n";
775         }
776     } else {
777         my $evil = "foo" . $TAINT;
778
779         eval { sysopen(my $ro, $evil, &O_RDONLY) };
780         test 156, $@ !~ /^Insecure dependency/, $@;
781         
782         eval { sysopen(my $wo, $evil, &O_WRONLY) };
783         test 157, $@ =~ /^Insecure dependency/, $@;
784         
785         eval { sysopen(my $rw, $evil, &O_RDWR) };
786         test 158, $@ =~ /^Insecure dependency/, $@;
787         
788         eval { sysopen(my $ap, $evil, &O_APPEND) };
789         test 159, $@ =~ /^Insecure dependency/, $@;
790         
791         eval { sysopen(my $cr, $evil, &O_CREAT) };
792         test 160, $@ =~ /^Insecure dependency/, $@;
793         
794         eval { sysopen(my $tr, $evil, &O_TRUNC) };
795         test 161, $@ =~ /^Insecure dependency/, $@;
796         
797         eval { sysopen(my $ro, "foo", &O_RDONLY | $evil) };
798         test 162, $@ !~ /^Insecure dependency/, $@;
799         
800         eval { sysopen(my $wo, "foo", &O_WRONLY | $evil) };
801         test 163, $@ =~ /^Insecure dependency/, $@;
802
803         eval { sysopen(my $rw, "foo", &O_RDWR | $evil) };
804         test 164, $@ =~ /^Insecure dependency/, $@;
805
806         eval { sysopen(my $ap, "foo", &O_APPEND | $evil) };
807         test 165, $@ =~ /^Insecure dependency/, $@;
808         
809         eval { sysopen(my $cr, "foo", &O_CREAT | $evil) };
810         test 166, $@ =~ /^Insecure dependency/, $@;
811
812         eval { sysopen(my $tr, "foo", &O_TRUNC | $evil) };
813         test 167, $@ =~ /^Insecure dependency/, $@;
814
815         eval { sysopen(my $ro, "foo", &O_RDONLY, $evil) };
816         test 168, $@ !~ /^Insecure dependency/, $@;
817         
818         eval { sysopen(my $wo, "foo", &O_WRONLY, $evil) };
819         test 169, $@ =~ /^Insecure dependency/, $@;
820         
821         eval { sysopen(my $rw, "foo", &O_RDWR, $evil) };
822         test 170, $@ =~ /^Insecure dependency/, $@;
823         
824         eval { sysopen(my $ap, "foo", &O_APPEND, $evil) };
825         test 171, $@ =~ /^Insecure dependency/, $@;
826         
827         eval { sysopen(my $cr, "foo", &O_CREAT, $evil) };
828         test 172, $@ =~ /^Insecure dependency/, $@;
829
830         eval { sysopen(my $tr, "foo", &O_TRUNC, $evil) };
831         test 173, $@ =~ /^Insecure dependency/, $@;
832         
833         unlink("foo"); # not unlink($evil), because that would fail...
834     }
835 }
836
837 {
838     # bug 20010526.004
839
840     use warnings;
841
842     $SIG{__WARN__} = sub { print "not " };
843
844     sub fmi {
845         my $divnum = shift()/1;
846         sprintf("%1.1f\n", $divnum);
847     }
848
849     fmi(21 . $TAINT);
850     fmi(37);
851     fmi(248);
852
853     print "ok 174\n";
854 }
855
856
857 {
858     # Bug ID 20010730.010
859
860     my $i = 0;
861
862     sub Tie::TIESCALAR {
863         my $class =  shift;
864         my $arg   =  shift;
865
866         bless \$arg => $class;
867     }
868
869     sub Tie::FETCH {
870         $i ++;
871         ${$_ [0]}
872     }
873
874  
875     package main;
876  
877     my $bar = "The Big Bright Green Pleasure Machine";
878     taint_these $bar;
879     tie my ($foo), Tie => $bar;
880
881     my $baz = $foo;
882
883     print $i == 1 ? "ok 175\n" : "not ok 175\n"
884
885 }
886
887 {
888     # Check that all environment variables are tainted.
889     my @untainted;
890     while (my ($k, $v) = each %ENV) {
891         if (!tainted($v) &&
892             # These we have untainted explicitly earlier.
893             $k !~ /^(BASH_ENV|CDPATH|ENV|IFS|PATH|TEMP|TERM|TMP)$/) {
894             push @untainted, "# '$k' = '$v'\n";
895         }
896     }
897     print @untainted == 0 ? "ok 176\n" : "not ok 176\n";
898     print "# untainted:\n", @untainted if @untainted; 
899 }
900
901
902 ok( ${^TAINT},  '$^TAINT is on' );
903
904 eval { ${^TAINT} = 0 };
905 ok( ${^TAINT},  '$^TAINT is not assignable' );
906 ok( $@ =~ /^Modification of a read-only value attempted/,
907                                 'Assigning to ${^TAINT} fails' );
908
909 {
910     # bug 20011111.105
911     
912     my $re1 = qr/x$TAINT/;
913     test 180, tainted $re1;
914     
915     my $re2 = qr/^$re1\z/;
916     test 181, tainted $re2;
917     
918     my $re3 = "$re2";
919     test 182, tainted $re3;
920 }
921
922 if ($Is_MSWin32) {
923     print "ok 183 # Skipped: system {} has different semantics\n"; 
924 }
925 else
926 {
927     # bug 20010221.005
928     local $ENV{PATH} .= $TAINT;
929     eval { system { "echo" } "/arg0", "arg1" };
930     test 183, $@ =~ /^Insecure \$ENV/;
931 }