This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #121854] use re 'taint' regression
authorDavid Mitchell <davem@iabyn.com>
Tue, 13 May 2014 13:18:06 +0000 (14:18 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 13 May 2014 14:20:54 +0000 (15:20 +0100)
commit1738e041e86c4796d194727eae67369600abf920
treef2d770365c5ae181fbdbe51f0e1008e43c8b2926
parent98830e71b322ee2b78a218cf29c6e32d7f94ff62
[perl #121854] use re 'taint' regression

Commit v5.19.8-533-g63baef5 changed the handling of locale-dependent
regexes so that the pattern was considered tainted at compile-time, rather
than determining it each time at run-time whenever it executed a
locale-dependent node. Unfortunately due to the conflating of two flags,
RXf_TAINTED and RXf_TAINTED_SEEN, it had the side effect of permanently
marking a pattern as tainted once it had had a single tainted result.

E.g.

    use re qw(taint);
    use Scalar::Util qw(tainted);
    for ($^X, "abc") {
        /(.*)/ or die;
        print "not " unless tainted("$1"); print "tainted\n";
    };

which from 5.19.9 onwards output:

    tainted
    tainted

but with this commit (and with 5.19.8 and earlier), it now outputs:

    tainted
    not tainted

The RXf_TAINTED flag indicates that the pattern itself is tainted, e.g.

    $r = qr/$tainted_value/

while the RXf_TAINTED_SEEN flag means that the results of the last match
are tainted, e.g.

    use re 'tainted';
    $tainted =~ /(.*)/;
    # $1 is tainted

Pre 63baef5, the code used to look like:

    at run-time:

        turn off RXf_TAINTED_SEEN;
        while (nodes to execute) {
            switch(node) {
            case
                BOUNDL: /* and other locale-specific ops */
                    turn on RXf_TAINTED_SEEN;
                    ...;
            }
        }
        if (tainted || RXf_TAINTED)
            turn on RXf_TAINTED_SEEN;

63baef5 changed it to:

    at compile-time:

        if (pattern has locale ops)
            turn on RXf_TAINTED_SEEN;

    at run-time:

        while (nodes to execute) {
            ...
        }
        if (tainted || RXf_TAINTED)
            turn on RXf_TAINTED_SEEN;

This commit changes it to:

    at compile-time;

        if (pattern has locale ops)
            turn on RXf_TAINTED;

    at run-time:

        turn off RXf_TAINTED_SEEN;
        while (nodes to execute) {
            ...
        }
        if (tainted || RXf_TAINTED)
            turn on RXf_TAINTED_SEEN;
pp_hot.c
regcomp.c
regexec.c
regexp.h
t/op/taint.t