webby has asked for the wisdom of the Perl Monks concerning the following question:

Hi, Can anyone tell me why this doesn't work when taint checking is turned on, but it does when it is off? I've read the perlsec stuff a few times, and don't see anything that resembles this situation.
my $class = 'Classes::SomeChild'; if {$class->isa('Classes::SomeParent')) { my $object = $class->new(); my $results = $object->doSomething(); }
OK, to be honest, $class is actually a variable that *was* tainted, but has since been untainted (definitely - even checked with the is_taint sub in perlsec), but it is just a scalar as in the example. When taint checking is not enabled, this works perfectly. When it is on, the following line returns undef:
$class->isa('Classes::SomeParent');
Why is it so?

Replies are listed 'Best First'.
Re: isa() and taint checking
by chromatic (Archbishop) on Oct 17, 2002 at 15:44 UTC

    This code works for me. You have to type 'Child' at the prompt.

    package Parent; package Child; @Child::ISA = 'Parent'; package main; chomp(my $in = <STDIN>); my $kid; if ($in =~ /(\w+)/) { $kid = $1; } print $kid->isa( 'Parent' ); print 'Child'->isa( 'Parent' );

    My guess is that your untainter isn't doing what you think it's doing.

      Hmmm... Interesting. This is the actual code, where $directory is hard coded above. The require line (require $file) was broken until I fixed the taint checking.
      if($file =~ /^(\w*\.pm)$/) { $file = $1; $file = $directory."/".$file; require $file; $file =~ s/\//::/g; $file =~ s/\.pm$//; if ($file->isa('Objects::Parent')) { my $object = $file->new(); $object->doSomething(); } }
Re: isa() and taint checking
by antifun (Sexton) on Oct 17, 2002 at 15:57 UTC
    Your code doesn't make any sense. Here's what I assume you are trying to do (which actually works when you run it, a characteristic that is useful for trying things out):
    package Classes::SomeParent; 1; package Classes::SomeChild; our @ISA=("Classes::SomeParent"); package main; my $class = 'Classes::SomeChild; my $obj = {}; bless $obj, 'Classes::SomeChild'; if ($obj->isa('Classes::SomeParent')) { print "Isa"; } else { print "Nota"; }
    prints "Isa". Likewise if you give it $class instead of $obj. My advice would be to directly inspect the @ISA of the relevant class in the debugger at that point to make sure it's correct. Of course, I am assuming that SomeChild is actually supposed to be a child of SomeParent, which you don't state.

    (NB: The "is_tainted" function in perlsec isn't doing what I expect it to -- to wit,

    print "Object is ". (is_tainted($obj) ? "not " : "") . "tainted";
    always claims that $obj is tainted.)

    Post some more, and maybe we can figure it out.
    ---
    "I hate it when I think myself into a corner."
    Matt Mitchell

      Sorry for being too brief.

      I've put together a longer example, and tested this. It works without -T, but I can't figure out why it won't work with Taint. Help is much appreciated.

      File 1 - example.pl
      #!/usr/bin/perl -wT use strict; use lib '.'; use Objects::Parent; loadObjects('Objects'); sub loadObjects { my $directory = shift; opendir(DIR, $directory) or die "Object Templates can't be loa +ded: Can't open $directory: $!"; while (defined(my $file = readdir(DIR))) { if($file =~ /^(.*\.pm)$/) { $file = $1; $file = $directory."/".$file; require $file; $file =~ s/\//::/g; $file =~ s/\.pm$//; if($file->isa('Objects::Parent')) { my $tempObject = $file->new(); $tempObject->doSomething(); } } } }
      File 2 - Objects/Parent.pm
      package Objects::Parent; sub new { bless {}, shift; } sub doSomething { print "Something\n"; } 1;
      File 3 - Objects/Child.pm
      package Objects::Child; use base 'Objects::Parent'; 1;

        A cheap hack to get around the problem:

        sub loadObjects { my $directory = shift; opendir(DIR, $directory) or die "Object Templates can't be loaded: Can't open $directory: $ +!"; while (defined(my $file = readdir(DIR))) { if($file =~ /^(.*\.pm)$/) { $file = $1; $file = $directory."/".$file; my $file = $file; # Cheap hack require $file; $file =~ s/\//::/g; $file =~ s/\.pm$//; if($file->isa('Objects::Parent')) { my $tempObject = $file->new(); $tempObject->doSomething(); } } }

        Otherwise, it looks to me like a bug in perl. *shrug* Maybe someone better than I can shed some light.

        bbfu
        Black flowers blossum
        Fearless on my breath

        OK. Something must be screwing up the tainting of $file, because if you change that isa test into this
        $file =~ /(.*)/; my $ff = $1; if ($ff->isa('Objects::Parent')) {
        it works as you'd expect.

        Now, I don't really know why this is the case. The Taint module's tainted function says $file isn't tainted. No error is ever seen, it just silently fails. My tests are on 5.6.1. Anyone have any better idea what's going on here?
        ---
        "I hate it when I think myself into a corner."
        Matt Mitchell