in reply to tainted entangled hashrefs

This is because the taintedness is held at the var level. So, clean and dirty are keys of the same variable. So, once one of them is dirty, the whole variable %foo is considered tainted. You are correct, it is guilt by assosiation, but it is there because $foo{dirty} is as foo as any other hash-key as far as Perl knows ... more foo than scalar as it were. the same way as arrays (if i recall).
can't sleep clowns will eat me
-- MZSanford

Replies are listed 'Best First'.
Re: Re: tainted entangled hashrefs
by Boldra (Curate) on Aug 22, 2001 at 20:42 UTC
    Thanks, your explanation does help. However it seems that in my example $foo is not tainted, (its value is "HASH(0x80f8a20)") - only the values of the hash reference are tainted (%$foo has become dirty because the value of one of the keys was bad). I think you knew this.

    Your explanation does mean I can push the tainted data down a level to clean up my hash-ref, eg:
    $dirty{text} = <>; $foo = { 'clean' => '/home/boldra/filename.txt', 'dirty' => \%dirty, }; open(F,"+>{$foo->{clean}}"); close(F);
    Which leaves $foo->{clean} clean as a whistle.

    But I still don't see why I have to do this. Is it because taint checking is simply clumsy, or is there actually a risk of a user supplying data that perl will accidentally interprect as the boundry between two values in an array?

    What I'm worrying about is: Is $foo->{clean} really tainted (in my original example) or is it a false positive by the taint-checking? If it's really tainted - what sort of cleaning does it need?

    Thanks,

    - Boldra
      I tested the following with "dirty" commented and uncommented:

      #!/usr/bin/perl -wT use strict; my $foo = { clean => 'test.dat', # dirty => scalar(<>), }; open (F,"+>{$foo->{clean}}"); close(F);

      As shown here, it ran with no error. That tells me that $foo->{clean} really is taint clean.

      yours,
      Michael

        I get an error if the "dirty" line is not commented, using perl 5.005_03, 5.6.0 and 5.6.1.

        - Boldra
      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