Hi. I have conflicting information on DBD::Pg's support for taint mode, and would like some clarification from you if possible.
Is there any way to tell DBD::Pg (or DBI) to raise an exception when prepare is invoked with a tainted SQL string? I thought this would be the default behavior, and was surprised when I ran the demo script below. This script requires four command-line arguments: the name of a database, the name of a table in that database, the name of an integer-type column in that table, and some integer. E.g., a run may look like this: $ perl -T demo_script.pl mydb mytable mycolum 42 1 1 1 1 1 1 NB: you will need to modify the user and password parameters in the call to DBI->connect. The important thing to note is that the connect, prepare, and execute methods all receive tainted arguments, but run without any problem. Furthermore, the subsequent fetchall_arrayref also runs without any problem. Many thanks in advance. Perl code follows. ~K #!/usr/bin/perl use strict; use warnings FATAL => 'all'; use DBI; my $dbname = shift; my $tablename = shift; my $colname = shift; my $id = shift; my $sql = qq(SELECT * FROM "$tablename" WHERE "$colname" = \$1;); my $connection_string = "dbi:Pg:dbname=$dbname"; # when this script is run under -T, the output from all the following # print statements is 1; if the script is *not* run under -T, then # they are all 0. print +(is_tainted($dbname) ? 1 : 0), "\n"; print +(is_tainted($tablename) ? 1 : 0), "\n"; print +(is_tainted($colname) ? 1 : 0), "\n"; print +(is_tainted($id) ? 1 : 0), "\n"; print +(is_tainted($connection_string) ? 1 : 0), "\n"; print +(is_tainted($sql) ? 1 : 0), "\n"; my $dbh = DBI->connect($connection_string, "kynn", undef, +{ RaiseError => 1, PrintError => 0, PrintWarn => 0, }); my $sth = $dbh->prepare($sql); $sth->execute($id); my $fetched = $sth->fetchall_arrayref; sub is_tainted { # this sub is adapted from Programming Perl, 3rd ed., p. 561 my $arg = shift; my $empty = do { no warnings 'uninitialized'; substr($arg, 0, 0); }; local $@; eval { eval "# $empty" }; return length($@) != 0; } ~K