зеркало из https://github.com/mozilla/gecko-dev.git
Use DBI placeholders to avoid SQL injection issues.
Bug #260894 r=timeless,justdave
This commit is contained in:
Родитель
8d09f98fb4
Коммит
47cb389e36
|
@ -41,25 +41,36 @@ validateRepository($CVS_ROOT);
|
|||
my $CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
ConnectToDatabase();
|
||||
&ConnectToDatabase();
|
||||
|
||||
my $f = SqlQuote($file);
|
||||
my $qstring = "select distinct dirs.dir from checkins,dirs,files,repositories where dirs.id=dirid and files.id=fileid and repositories.id=repositoryid and repositories.repository='$CVS_ROOT' and files.file=$f order by dirs.dir";
|
||||
my @bind_values = ( $CVS_ROOT, $file );
|
||||
my $qstring = "SELECT DISTINCT dirs.dir FROM checkins,dirs,files," .
|
||||
"repositories WHERE dirs.id=dirid AND files.id=fileid AND " .
|
||||
"repositories.id=repositoryid AND repositories.repository=? AND " .
|
||||
"files.file=? ORDER BY dirs.dir";
|
||||
|
||||
if ($debug) {
|
||||
print "<pre wrap>$qstring</pre>\n";
|
||||
print "<pre wrap>\n";
|
||||
print &html_quote($qstring) . "\n";
|
||||
print "With values:\n";
|
||||
foreach my $v (@bind_values) {
|
||||
print "\t" . &html_quote($v) . "\n";
|
||||
}
|
||||
print "</pre>\n";
|
||||
}
|
||||
|
||||
my (@row, $d, @fl, $s);
|
||||
|
||||
SendSQL($qstring);
|
||||
while(@row = FetchSQLData()){
|
||||
&SendSQL($qstring, @bind_values);
|
||||
while(@row = &FetchSQLData()){
|
||||
$d = $row[0];
|
||||
push @fl, "$d/$file";
|
||||
}
|
||||
&DisconnectFromDatabase();
|
||||
|
||||
if( @fl == 0 ){
|
||||
print "<h3>No files matched this file name. It may have been added recently.</h3>";
|
||||
print "<h3>No files matched this file name: " . &html_quote($file) .
|
||||
". It may have been added recently.</h3>";
|
||||
}
|
||||
elsif( @fl == 1 ){
|
||||
$s = &url_quote($fl[0]);
|
||||
|
@ -73,6 +84,6 @@ else {
|
|||
print "<h3>Pick the file that best matches the one you are looking for:</h3>\n";
|
||||
for $s (@fl) {
|
||||
print "<dt><a href=cvsblame.cgi?file=" . &url_quote($s) .
|
||||
"&rev=$rev&mark=$mark#$ln>$s</a>";
|
||||
"&rev=$rev&mark=$mark#$ln>" . &html_quote($s) . "</a>";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ sub query_checkins {
|
|||
my (%mod_map) = @_;
|
||||
my ($ci,$result,$lastlog,$rev,$begin_tag,$end_tag);
|
||||
my $have_mod_map;
|
||||
my @bind_values;
|
||||
|
||||
$::query_module = 'all' unless defined $::query_module;
|
||||
if( $::query_module ne 'all' && $::query_module ne 'allrepositories' && @::query_dirs == 0 ){
|
||||
|
@ -121,82 +122,96 @@ sub query_checkins {
|
|||
|
||||
$result = [];
|
||||
|
||||
ConnectToDatabase();
|
||||
&ConnectToDatabase();
|
||||
|
||||
my $qstring = "select type, UNIX_TIMESTAMP(ci_when), people.who, repositories.repository, dirs.dir, files.file, revision, stickytag, branches.branch, addedlines, removedlines, descs.description from checkins,people,repositories,dirs,files,branches,descs where people.id=whoid and repositories.id=repositoryid and dirs.id=dirid and files.id=fileid and branches.id=branchid and descs.id=descid";
|
||||
my $qstring = "SELECT type, UNIX_TIMESTAMP(ci_when), people.who, " .
|
||||
"repositories.repository, dirs.dir, files.file, revision, " .
|
||||
"stickytag, branches.branch, addedlines, removedlines, " .
|
||||
"descs.description FROM checkins,people,repositories,dirs,files," .
|
||||
"branches,descs WHERE people.id=whoid AND " .
|
||||
"repositories.id=repositoryid AND dirs.id=dirid AND " .
|
||||
"files.id=fileid AND branches.id=branchid AND descs.id=descid";
|
||||
|
||||
if( $::query_module ne 'allrepositories' ){
|
||||
$qstring .= " and repositories.repository = '$::CVS_ROOT'";
|
||||
$qstring .= " AND repositories.repository = ?";
|
||||
push(@bind_values, $::CVS_ROOT);
|
||||
}
|
||||
|
||||
if ($::query_date_min) {
|
||||
my $t = formatSqlTime($::query_date_min);
|
||||
$qstring .= " and ci_when >= '$t'";
|
||||
$qstring .= " AND ci_when >= ?";
|
||||
push(@bind_values, &formatSqlTime($::query_date_min));
|
||||
}
|
||||
if ($::query_date_max) {
|
||||
my $t = formatSqlTime($::query_date_max);
|
||||
$qstring .= " and ci_when <= '$t'";
|
||||
$qstring .= " AND ci_when <= ?";
|
||||
push(@bind_values, &formatSqlTime($::query_date_max));
|
||||
}
|
||||
if ($::query_branch_head) {
|
||||
$qstring .= " and branches.branch = ''";
|
||||
$qstring .= " AND branches.branch = ''";
|
||||
} elsif ($::query_branch ne '') {
|
||||
my $q = SqlQuote($::query_branch);
|
||||
if ($::query_branchtype eq 'regexp') {
|
||||
$qstring .=
|
||||
" and branches.branch regexp $q";
|
||||
$qstring .= " AND branches.branch REGEXP ?";
|
||||
push(@bind_values, $::query_branch);
|
||||
} elsif ($::query_branchtype eq 'notregexp') {
|
||||
if ($::query_branch eq 'HEAD') {
|
||||
$qstring .= " and branches.branch != ''";
|
||||
$qstring .= " AND branches.branch != ''";
|
||||
} else {
|
||||
$qstring .= " and not (branches.branch regexp $q) ";
|
||||
$qstring .= " and not (branches.branch REGEXP ?)";
|
||||
push(@bind_values, $::query_branch);
|
||||
}
|
||||
} else {
|
||||
$qstring .=
|
||||
" and (branches.branch = $q or branches.branch = ";
|
||||
$qstring .= SqlQuote("T$::query_branch") . ")";
|
||||
" AND (branches.branch = ? OR branches.branch = ?)";
|
||||
push(@bind_values, $::query_branch);
|
||||
push(@bind_values, "T$::query_branch");
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < @::query_dirs) {
|
||||
my @list;
|
||||
foreach my $i (@::query_dirs) {
|
||||
push(@list, "dirs.dir like " . SqlQuote("$i%"));
|
||||
push(@list, "dirs.dir LIKE ?");
|
||||
push(@bind_values, "$i%");
|
||||
}
|
||||
$qstring .= "and (" . join(" or ", @list) . ")";
|
||||
$qstring .= "AND (" . join(" OR ", @list) . ")";
|
||||
}
|
||||
|
||||
if (defined $::query_file && $::query_file ne '') {
|
||||
my $q = SqlQuote($::query_file);
|
||||
$::query_filetype ||= "exact";
|
||||
if ($::query_filetype eq 'regexp') {
|
||||
$qstring .= " and files.file regexp $q";
|
||||
} elsif ($::query_filetype eq 'notregexp') {
|
||||
$qstring .= " and not (files.file regexp $q)";
|
||||
$qstring .= " AND files.file REGEXP ?";
|
||||
} elsif ($::query_filetype eq 'notregexp') {
|
||||
$qstring .= " AND NOT (files.file REGEXP ?)";
|
||||
} else {
|
||||
$qstring .= " and files.file = $q";
|
||||
$qstring .= " AND files.file = ?";
|
||||
}
|
||||
push(@bind_values, $::query_file);
|
||||
}
|
||||
if (defined $::query_who && $::query_who ne '') {
|
||||
my $q = SqlQuote($::query_who);
|
||||
$::query_whotype ||= "exact";
|
||||
if ($::query_whotype eq 'regexp') {
|
||||
$qstring .= " and people.who regexp $q";
|
||||
$qstring .= " AND people.who REGEXP ?";
|
||||
}
|
||||
elsif ($::query_whotype eq 'notregexp') {
|
||||
$qstring .= " and not (people.who regexp $q)";
|
||||
$qstring .= " AND NOT (people.who REGEXP ?)";
|
||||
|
||||
} else {
|
||||
$qstring .= " and people.who = $q";
|
||||
$qstring .= " AND people.who = ?";
|
||||
}
|
||||
push(@bind_values, $::query_who);
|
||||
}
|
||||
|
||||
if (defined($::query_logexpr) && $::query_logexpr ne '') {
|
||||
my $q = SqlQuote($::query_logexpr);
|
||||
$qstring .= " and descs.description regexp $q";
|
||||
$qstring .= " AND descs.description regexp ?";
|
||||
push(@bind_values, $::query_logexpr);
|
||||
}
|
||||
|
||||
if ($::query_debug) {
|
||||
print "<pre wrap> Query: $qstring\nTreeID is $::TreeID\n";
|
||||
print "<pre wrap> Query: " . &html_quote($qstring) . "\n";
|
||||
print "With values:\n";
|
||||
foreach my $v (@bind_values) {
|
||||
print "\t" . &html_quote($v) . "\n";
|
||||
}
|
||||
print "\nTreeID is $::TreeID\n";
|
||||
if ($have_mod_map) {
|
||||
print "Dump of module map:\n";
|
||||
foreach my $k (sort(keys %mod_map)) {
|
||||
|
@ -211,7 +226,7 @@ sub query_checkins {
|
|||
print "</pre>\n";
|
||||
}
|
||||
|
||||
SendSQL($qstring);
|
||||
&SendSQL($qstring, @bind_values);
|
||||
|
||||
$lastlog = 0;
|
||||
my @row;
|
||||
|
|
|
@ -337,11 +337,11 @@ sub refigureStartDateIfNecessary {
|
|||
return;
|
||||
}
|
||||
|
||||
ConnectToDatabase();
|
||||
SendSQL("select min(ci_when)
|
||||
from checkins,repositories
|
||||
where repositories.id = repositoryid and
|
||||
repository = '$::CVS_ROOT'");
|
||||
&ConnectToDatabase();
|
||||
&SendSQL("SELECT MIN(ci_when)
|
||||
FROM checkins,repositories
|
||||
WHERE repositories.id = repositoryid and
|
||||
repository = ?", $::CVS_ROOT);
|
||||
|
||||
my $startdate = FetchOneColumn();
|
||||
if ($startdate eq "") {
|
||||
|
|
|
@ -125,13 +125,28 @@ sub DisconnectFromDatabase {
|
|||
}
|
||||
|
||||
sub SendSQL {
|
||||
my ($str) = (@_);
|
||||
my ($rows);
|
||||
my ($str, @bind_values) = (@_);
|
||||
my $status = 0;
|
||||
|
||||
$::currentquery = $::db->prepare($str)
|
||||
|| die "'$str': ". $::db->errstr;
|
||||
$rows = $::currentquery->execute
|
||||
|| die "'$str': Can't execute the query: " . $::currentquery->errstr;
|
||||
$::currentquery = $::db->prepare($str) || $status++;
|
||||
if ($status) {
|
||||
print STDERR "SendSQL prepare error: '$str' with values (";
|
||||
foreach my $v (@bind_values) {
|
||||
print STDERR "'" . &shell_escape($v) . "', ";
|
||||
}
|
||||
print STDERR ") :: " . $::db->errstr . "\n";
|
||||
die "Cannot prepare SQL query. Please contact system administrator.\n";
|
||||
}
|
||||
|
||||
$::currentquery->execute(@bind_values) || $status++;
|
||||
if ($status) {
|
||||
print STDERR "SendSQL execute error: '$str' with values (";
|
||||
foreach my $v (@bind_values) {
|
||||
print STDERR "'" . &shell_escape($v) . "', ";
|
||||
}
|
||||
print STDERR ") :: " . $::currentquery->errstr . "\n";
|
||||
die "Cannot execute SQL query. Please contact system administrator.\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub MoreSQLData {
|
||||
|
@ -150,7 +165,7 @@ sub FetchSQLData {
|
|||
undef @::fetchahead;
|
||||
return @result;
|
||||
}
|
||||
return $::currentquery->fetchrow();
|
||||
return $::currentquery->fetchrow_array();
|
||||
}
|
||||
|
||||
|
||||
|
@ -160,19 +175,6 @@ sub FetchOneColumn {
|
|||
}
|
||||
|
||||
|
||||
# This routine is largely copied from Mysql.pm.
|
||||
|
||||
sub SqlQuote {
|
||||
my ($str) = (@_);
|
||||
# if (!defined $str) {
|
||||
# confess("Undefined passed to SqlQuote");
|
||||
# }
|
||||
$str =~ s/([\\\'])/\\$1/g;
|
||||
$str =~ s/\0/\\0/g;
|
||||
return "'$str'";
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Fills in a hashtable with info about the columns for the given table in the
|
||||
# database. The hashtable has the following entries:
|
||||
|
@ -182,10 +184,10 @@ sub SqlQuote {
|
|||
sub LearnAboutColumns {
|
||||
my ($table) = (@_);
|
||||
my %a;
|
||||
SendSQL("show columns from $table");
|
||||
&SendSQL("SHOW columns FROM $table");
|
||||
my @list = ();
|
||||
my @row;
|
||||
while (@row = FetchSQLData()) {
|
||||
while (@row = &FetchSQLData()) {
|
||||
my ($name,$type) = (@row);
|
||||
$a{"$name,type"} = $type;
|
||||
push @list, $name;
|
||||
|
@ -224,9 +226,9 @@ sub SplitEnumType {
|
|||
sub PerlQuote {
|
||||
my ($str) = (@_);
|
||||
|
||||
$str = SqlQuote($str);
|
||||
|
||||
return $str;
|
||||
$str =~ s/([\\\'])/\\$1/g;
|
||||
$str =~ s/\0/\\0/g;
|
||||
return "'$str'";
|
||||
}
|
||||
|
||||
sub GenerateArrayCode {
|
||||
|
@ -328,20 +330,19 @@ undef %lastidcache;
|
|||
|
||||
sub GetId {
|
||||
my ($table, $field, $value) = @_;
|
||||
my ($index, $qvalue, $id);
|
||||
my ($index, $id);
|
||||
|
||||
$index = "$table|$field|$value";
|
||||
return ($lastidcache{$index})
|
||||
if (exists $lastidcache{$index});
|
||||
|
||||
$qvalue = SqlQuote($value);
|
||||
SendSQL("select id from $table where $field = $qvalue");
|
||||
($id) = FetchSQLData();
|
||||
&SendSQL("SELECT id FROM $table WHERE $field = ?", $value);
|
||||
($id) = &FetchSQLData();
|
||||
|
||||
unless ($id) {
|
||||
SendSQL("insert into $table ($field) values ($qvalue)");
|
||||
SendSQL("select LAST_INSERT_ID()");
|
||||
($id) = FetchSQLData();
|
||||
&SendSQL("INSERT INTO $table ($field) VALUES (?)", $value);
|
||||
&SendSQL("SELECT LAST_INSERT_ID()");
|
||||
($id) = &FetchSQLData();
|
||||
}
|
||||
|
||||
return ($lastidcache{$index} = $id);
|
||||
|
@ -350,16 +351,15 @@ sub GetId {
|
|||
|
||||
sub GetId_NoCache {
|
||||
my ($table, $field, $value) = @_;
|
||||
my ($qvalue, $id);
|
||||
my ($id);
|
||||
|
||||
$qvalue = SqlQuote($value);
|
||||
SendSQL("select id from $table where $field = $qvalue");
|
||||
($id) = FetchSQLData();
|
||||
&SendSQL("SELECT id FROM $table WHERE $field = ?", $value);
|
||||
($id) = &FetchSQLData();
|
||||
|
||||
unless ($id) {
|
||||
SendSQL("insert into $table ($field) values ($qvalue)");
|
||||
SendSQL("select LAST_INSERT_ID()");
|
||||
($id) = FetchSQLData();
|
||||
&SendSQL("INSERT INTO $table ($field) values (?)", $value);
|
||||
&SendSQL("SELECT LAST_INSERT_ID()");
|
||||
($id) = &FetchSQLData();
|
||||
}
|
||||
|
||||
return $id;
|
||||
|
@ -386,17 +386,18 @@ sub MakeValueHash {
|
|||
|
||||
sub GetHashedId {
|
||||
my ($table, $field, $value) = @_;
|
||||
my ($qvalue, $id, $hash);
|
||||
my (@bind_values, $id);
|
||||
|
||||
$hash = MakeValueHash($value);
|
||||
$qvalue = SqlQuote($value);
|
||||
SendSQL("select id from $table where hash = $hash and $field = $qvalue");
|
||||
($id) = FetchSQLData();
|
||||
@bind_values = (&MakeValueHash($value), $value);
|
||||
&SendSQL("SELECT id FROM $table WHERE hash = ? AND $field = ?",
|
||||
@bind_values);
|
||||
($id) = &FetchSQLData();
|
||||
|
||||
unless ($id) {
|
||||
SendSQL("insert into $table (hash, $field) values ($hash, $qvalue)");
|
||||
SendSQL("select LAST_INSERT_ID()");
|
||||
($id) = FetchSQLData();
|
||||
&SendSQL("INSERT INTO $table (hash, $field) values (?, ?)",
|
||||
@bind_values);
|
||||
&SendSQL("SELECT LAST_INSERT_ID()");
|
||||
($id) = &FetchSQLData();
|
||||
}
|
||||
|
||||
return $id;
|
||||
|
@ -410,7 +411,7 @@ undef $lastdescription;
|
|||
|
||||
sub AddToDatabase {
|
||||
my ($lines, $desc) = @_;
|
||||
my ($descid, $basequery, $query, $line, $quoted);
|
||||
my ($descid, $basequery, $query, $line, @bind_values);
|
||||
my ($chtype, $date, $name, $repository, $dir);
|
||||
my ($file, $version, $sticky, $branch, $addlines, $removelines);
|
||||
|
||||
|
@ -426,12 +427,12 @@ sub AddToDatabase {
|
|||
}
|
||||
|
||||
# Build the query...
|
||||
$basequery = "replace into
|
||||
$basequery = "REPLACE INTO
|
||||
checkins(
|
||||
type, ci_when, whoid, repositoryid, dirid,
|
||||
fileid, revision, stickytag, branchid, addedlines,
|
||||
removedlines, descid)
|
||||
values (";
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
foreach $line (split(/\n/, $lines)) {
|
||||
next if ($line =~ /^\s*$/);
|
||||
|
@ -455,8 +456,7 @@ sub AddToDatabase {
|
|||
|
||||
# Find the description id, if it isn't already set
|
||||
if (!defined($descid)) {
|
||||
$descid = GetHashedId('descs', 'description', $desc);
|
||||
$quoted = SqlQuote($desc);
|
||||
$descid = &GetHashedId('descs', 'description', $desc);
|
||||
$lastdescriptionid = $descid;
|
||||
$lastdescription = $desc;
|
||||
}
|
||||
|
@ -464,28 +464,27 @@ sub AddToDatabase {
|
|||
# Build the final query
|
||||
$query = $basequery;
|
||||
if ($chtype eq "C") {
|
||||
$query .= "'Change'";
|
||||
$chtype = 'Change';
|
||||
} elsif ($chtype eq "A") {
|
||||
$query .= "'Append'";
|
||||
$chtype = 'Append';
|
||||
} elsif ($chtype eq "R") {
|
||||
$query .= "'Remove'";
|
||||
$chtype = 'Remove';
|
||||
} else {
|
||||
$query .= "NULL";
|
||||
$chtype = "NULL";
|
||||
}
|
||||
|
||||
$query .= ", '$date'";
|
||||
$query .= ", " . GetId("people", "who", $name);
|
||||
$query .= ", " . GetId("repositories", "repository", $repository);
|
||||
$query .= ", " . GetId("dirs", "dir", $dir);
|
||||
$query .= ", " . GetId("files", "file", $file);
|
||||
$query .= ", " . SqlQuote($version);
|
||||
$query .= ", " . SqlQuote($sticky);
|
||||
$query .= ", " . GetId("branches", "branch", $branch);
|
||||
$query .= ", $addlines";
|
||||
$query .= ", $removelines";
|
||||
$query .= ", $descid)";
|
||||
|
||||
SendSQL($query);
|
||||
@bind_values = ($chtype,
|
||||
$date,
|
||||
&GetId("people", "who", $name),
|
||||
&GetId("repositories", "repository", $repository),
|
||||
&GetId("dirs", "dir", $dir),
|
||||
&GetId("files", "file", $file),
|
||||
$version,
|
||||
$sticky,
|
||||
&GetId("branches", "branch", $branch),
|
||||
$addlines,
|
||||
$removelines,
|
||||
$descid);
|
||||
&SendSQL($query, @bind_values);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,9 +67,21 @@ Searching for first checkin after " . SqlFmtClock($startfrom) . "...<p>\n";
|
|||
my $inbranch = $::TreeInfo{$::TreeID}->{'branch'};
|
||||
print "<p> $inbranch <p> \n";
|
||||
|
||||
my $sqlstring = "select type, UNIX_TIMESTAMP(ci_when), people.who, repositories.repository, dirs.dir, files.file, revision, stickytag, branches.branch, addedlines, removedlines, descs.description from checkins,people,repositories,dirs,files,branches,descs where people.id=whoid and repositories.id=repositoryid and dirs.id=dirid and files.id=fileid and branches.id=branchid and descs.id=descid and branches.branch='$inbranch' and ci_when>='" . SqlFmtClock($startfrom) . "' order by ci_when;";
|
||||
print "<p> $sqlstring <p>\n";
|
||||
SendSQL("$sqlstring");
|
||||
my $sqlstring = "SELECT type, UNIX_TIMESTAMP(ci_when), people.who, " .
|
||||
"repositories.repository, dirs.dir, files.file, revision, stickytag, " .
|
||||
"branches.branch, addedlines, removedlines, descs.description FROM " .
|
||||
"checkins,people,repositories,dirs,files,branches,descs WHERE " .
|
||||
"people.id=whoid AND repositories.id=repositoryid AND dirs.id=dirid " .
|
||||
"AND files.id=fileid AND branches.id=branchid AND descs.id=descid AND " .
|
||||
"branches.branch=? AND ci_when>=? ORDER BY ci_when;";
|
||||
my @bind_values = ($inbranch, &SqlFmtClock($startfrom));
|
||||
print "<p> " . &html_quote($sqlstring) . " <br>\n";
|
||||
print "With values:<br>\n";
|
||||
foreach my $v (@bind_values) {
|
||||
print "\t" . &html_quote($v) . "<br>\n";
|
||||
}
|
||||
print "<p>\n";
|
||||
&SendSQL($sqlstring, @bind_values);
|
||||
|
||||
my ($change, $date, $who, $repos, $dir, $file, $rev, $sticky, $branch, $linesa, $linesr, $log);
|
||||
my ($lastchange, $lastdate, $lastwho, $lastrepos, $lastdir, $lastrev, $laststicky, $lastbranch, $lastlinesa, $lastlinesr, $lastlog);
|
||||
|
|
Загрузка…
Ссылка в новой задаче