http://qs1969.pair.com?node_id=640094

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

Could someone explains why this detects if a variable is tainted?
return ! eval { join('',@_), kill 0; 1; }; }
I assume the key is "vairable,kill 0". I checked the kill func, it returns 0 on success and > 0 on failure. So kill 0 will always return success; Does this mean the variable you pass into this function is always going to come out tainted? Thanks.

Replies are listed 'Best First'.
Re: is_tainted function
by dave_the_m (Monsignor) on Sep 20, 2007 at 13:00 UTC
    Tainting works per statement: if any tainted values are seen during execution of that statement, the rest of the statement is marked as tainted for the purposes of refusing to execute tainted code. kill is one such built-in that dies if it detects taintedness:
    $ perl -T -e 'kill $ARGV[0]' 0 Insecure dependency in kill while running with -T switch at -e line 1. $ perl -T -e '$ARGV[0], kill 0' 0 Insecure dependency in kill while running with -T switch at -e line 1. $ perl -T -e '$ARGV[0]; kill 0' 0 $

    Dave.

Re: is_tainted function
by Anonymous Monk on Sep 20, 2007 at 14:07 UTC
    http://search.cpan.org/~nwclark/perl-5.8.8/pod/perlsec.pod#Laundering_and_Detecting_Tainted_Data
    Laundering and Detecting Tainted Data To test whether a variable contains tainted data, and whose use would +thus trigger an "Insecure dependency" message, you can use the tainte +d() function of the Scalar::Util module, available in your nearby CPA +N mirror, and included in Perl starting from the release 5.8.0. Or yo +u may be able to use the following is_tainted() function. sub is_tainted { return ! eval { eval("#" . substr(join("", @_), 0, 0)); 1 }; } This function makes use of the fact that the presence of tainted data +anywhere within an expression renders the entire expression tainted. +It would be inefficient for every operator to test every argument for + taintedness. Instead, the slightly more efficient and conservative a +pproach is used that if any tainted value has been accessed within th +e same expression, the whole expression is considered tainted. But testing for taintedness gets you only so far. Sometimes you have j +ust to clear your data's taintedness. Values may be untainted by usin +g them as keys in a hash; otherwise the only way to bypass the tainti +ng mechanism is by referencing subpatterns from a regular expression +match. Perl presumes that if you reference a substring using $1, $2, +etc., that you knew what you were doing when you wrote the pattern. T +hat means using a bit of thought--don't just blindly untaint anything +, or you defeat the entire mechanism. It's better to verify that the +variable has only good characters (for certain values of "good") rath +er than checking whether it has any bad characters. That's because it +'s far too easy to miss bad characters that you never thought of.
Re: is_tainted function
by amarquis (Curate) on Sep 20, 2007 at 13:00 UTC

    As to your main question, sadly, I don't know.

    But my reading of the Kill function leads me to different conclusions. Kill seems to return the number of processes successfully signaled (processes sent in a list after the signal. The signal zero sends no signals, and there is no list, so that should always return zero.

    Now, if that eval block gets to the "1;", it is because the join went off without a hitch because the stuff in @_ wasn't tainted. So the eval returns 1, the not turns it into false: the variables were not tainted.

    If they are tainted, I'm not totally sure what is happening (most of this is guesswork, I'm not that good/experienced with Perl). I'm guessing that the join wets the bed and fails, the "kill" returns 0 (no processes were signaled), the eval grinds to a halt and returns the 0. The not turns that into a true, the variables were in fact tainted.

    Again, not that experienced, may be way off base here.

    Edit: Dave swooped in with the correct answer. I'm going to go back to reading "Programming Perl."

      signal 0 is special. In that case, the return value is the number of processes that would have been signalled if you'd sent a valid signal number. In other words, it checks to see if process IDs exist.