from my understanding, this is mostly a problem with Taint-checking being clumsy.
using <> does not give the input line the ability to modify %foo (unless you eval'd it and then it would taint anything it touches), so the keys other than dirty should
stay clean, but they do not. I believe this is an implimentation detail (or bug?) in taint checking that makes all keys in a hash
share the same taint-state. Maybe someone with a bit more source knowlege could confirm that ? I will start check source myself, and will post an
update if i find anything.
Update : Now i am getting too far into this (Trees? What trees ? i am in a forest !), and have found that normal hashes do not suffer this. So, in Perl 5.6.0 i used :
%ENV = ();
%foo = (
clean => '/usr/matt/.netrc',
dirty => (<>),
);
print "$foo{clean}\n";
sleep 1;
print "$foo{dirty}\n";
sleep 2;
system("ls $foo{clean}"); # ok
system("ls $foo{dirty}"); # error
but failed on a hash ref. ... still looking.
Update Again : Ok, here is an odd one, here is my test code :
$| = 1;
%ENV = ();
%foo = (
clean => '/usr/matt/.netrc',
dirty => (<>),
);
$bar = {
clean => '/usr/matt/.profile',
dirty => (<>),
};
$and = \%foo;
print "Foo\n";
print "1 : " ; system("echo $foo{clean} > /dev/null 2>&1");
print "2 : " ; system("echo $foo{dirty} > /dev/null 2>&1");
print "Bar\n";
print "1 : " ; system("echo \"$bar\" > /dev/null 2>&1");
print "2 : " ; system("echo $bar->{clean} > /dev/null 2>&1");
print "3 : " ; system("echo $bar->{dirty} > /dev/null 2>&1");
print "And\n";
print "1 : " ; system("echo \"$and\" > /dev/null 2>&1");
print "2 : " ; system("echo $and->{clean} > /dev/null 2>&1");
print "3 : " ; system("echo $and->{dirty} > /dev/null 2>&1");
And the output is :
%shell > perl -Du -U -T taintme.pl
EXECUTING...
a
^D
b
^D
Foo
1 : system 0 30004 30004
2 : system 1 30004 30004
a
Bar
1 : system 0 30004 30004
2 : system 1 30004 30004
3 : system 1 30004 30004
And
1 : system 0 30004 30004
2 : system 0 30004 30004
3 : system 1 30004 30004
a
I am now seeing this is something with the anonhash specifically, and assiging a hash-ref to an extsing hash will allow key access. Unsure why.
Update 3: anymore updates and i will create a new node. I added some code to my last test script and got yet another oddity. I added :
$another = +{};
$another->{clean} = '/usr/matt/.kshrc';
$another->{dirty} = (<>);
# and also
print "1 : " ; system("echo \"$another\" > /dev/null 2>&1");
print "2 : " ; system("echo $another->{clean} > /dev/null 2>&1");
print "3 : " ; system("echo $another->{dirty} > /dev/null 2>&1");
and to my suprise i got :
Another
1 : system 0 30004 30004
2 : system 0 30004 30004
3 : system 1 30004 30004
... so, now i think it is a bug in how tainting is assigned during the assigment. Maybe it taints everything in the {} block as a group ? thats about all i have at this point. hmmm... looking at perl -Dut -U -T taintme.pl i see that the code is parsed, and not until the end of the block it is decalred a anonymous hash. So, because it could be a code ref (maybe? i'm guessing) the taint covers the whole block. My fix is to assign dirty element seperatly line $another above.
Update (last) : Per CB request , here is the fix fo the code :
Taint bad ...
#!/usr/bin/perl -wT
#
use strict;
my $foo = {
'clean' => 'filename.txt',
'dirty' => scalar(<>),
};
open(F,"+>{$foo->{clean}}");
close(F);
... and taint ok ...
#!/usr/bin/perl -wT
#
use strict;
my $foo{clean} = 'filename.txt';
$foo{dirty} = scalar(<>);
open(F,"+>{$foo->{clean}}");
close(F);
can't sleep clowns will eat me
-- MZSanford
|