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

I have a few strings I need to "fix" so I got get SQL injected. I have a couple variables I pull from url_param that I figure the easiest way to ensure they are GOOD is make a list of the half a dozen or so correct options it could be and remove anything else.

So if I have an array of my words that are accepted: my @good_words = qq(red blue green brown); how would I get a s/// regex on $input to remove anything but the words found in @good_words?

  • Comment on Simple regex to remove all but a list of words

Replies are listed 'Best First'.
Re: Simple regex to remove all but a list of words
by moritz (Cardinal) on Jun 04, 2008 at 21:39 UTC
    The right way to prevent SQL injection is to use DBI with placeholders instead of interpolating values into SQL.

    If you still want to use a regex, it might work like this:

    # with regex: my $regex = join '|', @good_words; if (param('evil') =~ m/\A(?:$re)\z/){ print "good param\n"; } # with a hash: my %whitelist; @whitelist{@good_words} = (1) x @good_words; if ($whitelist{param('evil')}){ print "good param\n"; }
      my %whitelist; @whitelist{@good_words} = (1) x @good_words;
      my %whitelist = map { $_ => 1 } @good_words;

      Is a better idiom (IMO, of course), because I hate having to use a declaration followed by an initialisation.


      Unless I state otherwise, all my code runs with strict and warnings
        So we can start the battle of style: would you rather have a clumsy, useless loop (or map), or rather two clumsy, lines, one with declaration, one with initialization?

        Perl 6 to the help, if you don't mind wrapping your head around function style a bit, you can use the zip operator Z:

        pugs> my @good = <a b c> ("a", "b", "c") pugs> @good Z 1 xx @good (("a", 1), ("b", 1), ("c", 1))

        Pugs doesn't flatten the list correctly, so you can't assign it to a hash in pugs, but a correct implementation will allow that. (Notice also the beauty of not needing any grouping parenthesis, because the precedence levels are just right(tm)).

        # Perl 6: my %hash = @good Z 1 xx @good
Re: Simple regex to remove all but a list of words
by FunkyMonk (Bishop) on Jun 04, 2008 at 21:46 UTC
    I hope you meant my @good_words = qw(red blue green brown);

    It's qw, not qq, to populate an array.


    Unless I state otherwise, all my code runs with strict and warnings
Re: Simple regex to remove all but a list of words
by ikegami (Patriarch) on Jun 04, 2008 at 21:41 UTC

    I figure the easiest way to ensure they are GOOD is make a list of the half a dozen or so correct options it could be and remove anything else.

    It's easiest to use placeholders or a combination of $dbh->quote and $dbh->quote_identifier.