1*e0c4386eSCy Schubert#!perl -T 2*e0c4386eSCy Schubert# Tests for taint-mode features 3*e0c4386eSCy Schubert 4*e0c4386eSCy Schubertuse strict; 5*e0c4386eSCy Schubertuse warnings; 6*e0c4386eSCy Schubertuse lib 'blib/lib'; 7*e0c4386eSCy Schubertuse Test::More tests => 21; 8*e0c4386eSCy Schubertuse File::Temp; 9*e0c4386eSCy Schubert 10*e0c4386eSCy Schubertuse_ok 'Text::Template' or exit 1; 11*e0c4386eSCy Schubert 12*e0c4386eSCy Schubertif ($^O eq 'MSWin32') { 13*e0c4386eSCy Schubert # File::Temp (for all versions up to at least 0.2308) is currently bugged under MSWin32/taint mode [as of 2018-09] 14*e0c4386eSCy Schubert # ... fails unless "/tmp" on the current windows drive is a writable directory OR either $ENV{TMP} or $ENV{TEMP} are untainted and point to a writable directory 15*e0c4386eSCy Schubert # ref: [File-Temp: Fails under -T, Windows 7, Strawberry Perl 5.12.1](https://rt.cpan.org/Public/Bug/Display.html?id=60340) 16*e0c4386eSCy Schubert ($ENV{TEMP}) = $ENV{TEMP} =~ m/^.*$/gmsx; # untaint $ENV{TEMP} 17*e0c4386eSCy Schubert ($ENV{TMP}) = $ENV{TMP} =~ m/^.*$/gmsx; # untaint $ENV{TMP} 18*e0c4386eSCy Schubert} 19*e0c4386eSCy Schubert 20*e0c4386eSCy Schubertmy $tmpfile = File::Temp->new; 21*e0c4386eSCy Schubertmy $file = $tmpfile->filename; 22*e0c4386eSCy Schubert 23*e0c4386eSCy Schubert# makes its arguments tainted 24*e0c4386eSCy Schubertsub taint { 25*e0c4386eSCy Schubert for (@_) { 26*e0c4386eSCy Schubert $_ .= substr($0, 0, 0); # LOD 27*e0c4386eSCy Schubert } 28*e0c4386eSCy Schubert} 29*e0c4386eSCy Schubert 30*e0c4386eSCy Schubertmy $template = 'The value of $n is {$n}.'; 31*e0c4386eSCy Schubert 32*e0c4386eSCy Schubertopen my $fh, '>', $file or die "Couldn't write temporary file $file: $!"; 33*e0c4386eSCy Schubertprint $fh $template, "\n"; 34*e0c4386eSCy Schubertclose $fh or die "Couldn't finish temporary file $file: $!"; 35*e0c4386eSCy Schubert 36*e0c4386eSCy Schubertsub should_fail { 37*e0c4386eSCy Schubert my $obj = Text::Template->new(@_); 38*e0c4386eSCy Schubert eval { $obj->fill_in() }; 39*e0c4386eSCy Schubert if ($@) { 40*e0c4386eSCy Schubert pass $@; 41*e0c4386eSCy Schubert } 42*e0c4386eSCy Schubert else { 43*e0c4386eSCy Schubert fail q[didn't fail]; 44*e0c4386eSCy Schubert } 45*e0c4386eSCy Schubert} 46*e0c4386eSCy Schubert 47*e0c4386eSCy Schubertsub should_work { 48*e0c4386eSCy Schubert my $obj = Text::Template->new(@_); 49*e0c4386eSCy Schubert eval { $obj->fill_in() }; 50*e0c4386eSCy Schubert if ($@) { 51*e0c4386eSCy Schubert fail $@; 52*e0c4386eSCy Schubert } 53*e0c4386eSCy Schubert else { 54*e0c4386eSCy Schubert pass; 55*e0c4386eSCy Schubert } 56*e0c4386eSCy Schubert} 57*e0c4386eSCy Schubert 58*e0c4386eSCy Schubertsub should_be_tainted { 59*e0c4386eSCy Schubert ok !Text::Template::_is_clean($_[0]); 60*e0c4386eSCy Schubert} 61*e0c4386eSCy Schubert 62*e0c4386eSCy Schubertsub should_be_clean { 63*e0c4386eSCy Schubert ok Text::Template::_is_clean($_[0]); 64*e0c4386eSCy Schubert} 65*e0c4386eSCy Schubert 66*e0c4386eSCy Schubert# Tainted filename should die with and without UNTAINT option 67*e0c4386eSCy Schubert# untainted filename should die without UNTAINT option 68*e0c4386eSCy Schubert# filehandle should die without UNTAINT option 69*e0c4386eSCy Schubert# string and array with tainted data should die either way 70*e0c4386eSCy Schubert 71*e0c4386eSCy Schubert# (2)-(7) 72*e0c4386eSCy Schubertmy $tfile = $file; 73*e0c4386eSCy Schuberttaint($tfile); 74*e0c4386eSCy Schubertshould_be_tainted($tfile); 75*e0c4386eSCy Schubertshould_be_clean($file); 76*e0c4386eSCy Schubertshould_fail TYPE => 'file', SOURCE => $tfile; 77*e0c4386eSCy Schubertshould_fail TYPE => 'file', SOURCE => $tfile, UNTAINT => 1; 78*e0c4386eSCy Schubertshould_fail TYPE => 'file', SOURCE => $file; 79*e0c4386eSCy Schubertshould_work TYPE => 'file', SOURCE => $file, UNTAINT => 1; 80*e0c4386eSCy Schubert 81*e0c4386eSCy Schubert# (8-9) 82*e0c4386eSCy Schubertopen $fh, '<', $file or die "Couldn't open $file for reading: $!; aborting"; 83*e0c4386eSCy Schubertshould_fail TYPE => 'filehandle', SOURCE => $fh; 84*e0c4386eSCy Schubertclose $fh; 85*e0c4386eSCy Schubert 86*e0c4386eSCy Schubertopen $fh, '<', $file or die "Couldn't open $file for reading: $!; aborting"; 87*e0c4386eSCy Schubertshould_work TYPE => 'filehandle', SOURCE => $fh, UNTAINT => 1; 88*e0c4386eSCy Schubertclose $fh; 89*e0c4386eSCy Schubert 90*e0c4386eSCy Schubert# (10-15) 91*e0c4386eSCy Schubertmy $ttemplate = $template; 92*e0c4386eSCy Schuberttaint($ttemplate); 93*e0c4386eSCy Schubertshould_be_tainted($ttemplate); 94*e0c4386eSCy Schubertshould_be_clean($template); 95*e0c4386eSCy Schubertshould_fail TYPE => 'string', SOURCE => $ttemplate; 96*e0c4386eSCy Schubertshould_fail TYPE => 'string', SOURCE => $ttemplate, UNTAINT => 1; 97*e0c4386eSCy Schubertshould_work TYPE => 'string', SOURCE => $template; 98*e0c4386eSCy Schubertshould_work TYPE => 'string', SOURCE => $template, UNTAINT => 1; 99*e0c4386eSCy Schubert 100*e0c4386eSCy Schubert# (16-19) 101*e0c4386eSCy Schubertmy $array = [$template]; 102*e0c4386eSCy Schubertmy $tarray = [$ttemplate]; 103*e0c4386eSCy Schubertshould_fail TYPE => 'array', SOURCE => $tarray; 104*e0c4386eSCy Schubertshould_fail TYPE => 'array', SOURCE => $tarray, UNTAINT => 1; 105*e0c4386eSCy Schubertshould_work TYPE => 'array', SOURCE => $array; 106*e0c4386eSCy Schubertshould_work TYPE => 'array', SOURCE => $array, UNTAINT => 1; 107*e0c4386eSCy Schubert 108*e0c4386eSCy Schubert# (20-21) Test _unconditionally_untaint utility function 109*e0c4386eSCy SchubertText::Template::_unconditionally_untaint($ttemplate); 110*e0c4386eSCy Schubertshould_be_clean($ttemplate); 111*e0c4386eSCy SchubertText::Template::_unconditionally_untaint($tfile); 112*e0c4386eSCy Schubertshould_be_clean($tfile); 113