in reply to hard-to-understand taint error

readdir is an unsafe operation and therefore its results are tainted. grep doesn't clean the tainted data as it will pass on the original data when its value is TRUE. You have to pass the data itself through a regular expression to clean them.

CountZero

A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Replies are listed 'Best First'.
Re^2: hard-to-understand taint error
by cmac (Monk) on Feb 18, 2009 at 08:39 UTC
    I cooked up a regexp for "how the filenames to be deleted should look" and now the taint checking is happy:
    my @dels = (); opendir DIR, DB_DIREC or die "can't open direc ".DB_DIREC.": $!"; for (readdir DIR) { if (/^(__[-!#.0-9@-Z_a-z]+)$/) {push @dels, DB_DIREC."/$1"} } closedir DIR; if (@dels) {unlink @dels}
    Thanks for your help,
    cmac
    www.animalhead.com

      That regex won't capture files with UC letters

      #!/usr/bin/perl use warnings; use strict; # 744661 my @var = [ 'foo.Bar', 'for.bar', ]; for my $var(@var) { if ( $var =~ /^(__[-!#.0-9@-Z_a-z]+)$/ ) { print "\$var: $var\n"; } else { print "no match!\n"; } }

      If you're concerned about files like "foo.Bar", use the /i modifier.

        Not true. [@-Z] is an obfuscated way of writing [\@A-Z]. Your test fails for two reasons:
        • Your array only contains one element and it's an array reference.
        • Your file names don't start with __.

      It looks like your original requirement was files starting with '__'.

      Similar to what ww is saying, you can simplify your capture to /^(__.*)$/; then you won't have to worry about upper-case matching.

        But since we already grepped for /^__/, that can be simplified /^(.*)$/. Looks scary, but it's fine here. Either we trust DB_DIREC or we don't (in which case, it could be used to delete /etc/__important even with the "safer" untainting).
Re^2: hard-to-understand taint error
by cmac (Monk) on Feb 18, 2009 at 06:50 UTC
    Changed the for statement in the previous sequence to:
    for (@dels) {s!(.+)!DB_DIREC."/$1"!e}
    Now everything goes through a regular expression and the same error results.
      As you have found out yourself, you must take the captured data outside of the regex in order to untaint it.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James