package MyApp::Schema::Result::Hash;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('hash');
__PACKAGE__->add_columns(qw/ key value /);
__PACKAGE__->set_primary_key('key');
1;
package MyApp::Schema;
use base qw/DBIx::Class::Schema/;
__PACKAGE__->register_class(Hash => "MyApp::Schema::Result::Hash");
1;
package main;
use warnings; use strict; use 5.010;
use DBI;
my $DB_FILE = "test.sqlite";
unlink $DB_FILE;
my @DSN = ("dbi:SQLite:dbname=$DB_FILE","","", { AutoCommit => 1, RaiseError => 1 });
DBI->connect(@DSN)->do($_) for split /\n/, <<'INIT';
CREATE TABLE hash (key text, value text);
INSERT INTO hash VALUES ('foo', 'FOO');
INSERT INTO hash VALUES ('bar', 'BAR');
INSERT INTO hash VALUES ('baz', 123);
INIT
####
my $schema = MyApp::Schema->connect(@DSN);
my $hash = $schema->resultset("Hash");
my $good_key = "key";
say $hash->search({ $good_key => "foo" })->count;
## executes: SELECT COUNT( * ) FROM hash me WHERE ( key = ? ): 'foo'
## says 1
my $evil_key = "1 = 1 ) --";
say $hash->search({ $evil_key => "foo" })->count;
## executes: SELECT COUNT( * ) FROM hash me WHERE ( 1 = 1 ) -- = ? ): 'foo'
## says 3
##
##
$schema->storage->sql_maker->quote_char('"');
say $hash->search({ $evil_key => "foo" })->count;
## executes: SELECT COUNT( * ) FROM "hash" "me" WHERE ( "1 = 1 ) --" = ? ): 'foo'
## says 0
##
##
my $evil_key2 = 'key" = "key" ) -- ';
say $hash->search({ $evil_key2 => "foo" })->count;
## executes: SELECT COUNT( * ) FROM "hash" "me" WHERE ( "key" = "key" ) -- " = ? ): 'foo'
## says 3
##
##
$schema->storage->sql_maker->quote_char(undef);
my $Q_evil_key2 = $schema->storage->dbh->quote_identifier($evil_key2);
say $hash->search({ $Q_evil_key2 => "foo" })->count;
## executes: SELECT COUNT( * ) FROM hash me WHERE ( "key"" = ""key"" ) -- " = ? ): 'foo'
## says 0