Closed
Bug 303695
Opened 19 years ago
Closed 18 years ago
Eliminate deprecated Bugzilla::DB routines from post_bug.cgi
Categories
(Bugzilla :: Bugzilla-General, enhancement)
Tracking
()
RESOLVED
FIXED
Bugzilla 3.0
People
(Reporter: wicked, Assigned: gabriel.sales)
References
Details
Attachments
(1 file, 3 obsolete files)
11.36 KB,
patch
|
LpSolit
:
review+
|
Details | Diff | Splinter Review |
These lines need to rewritten to use DBI: post_bug.cgi:127:my $sql_product = SqlQuote($cgi->param('product')); post_bug.cgi:128:my $sql_component = SqlQuote($cgi->param('component')); post_bug.cgi:132: SendSQL("SELECT initialowner FROM components " . post_bug.cgi:134: $cgi->param(-name => 'assigned_to', -value => FetchOneColumn()); post_bug.cgi:159: SendSQL("SELECT initialqacontact FROM components " . post_bug.cgi:161: $qa_contact = FetchOneColumn(); post_bug.cgi:180: SendSQL("SELECT votestoconfirm FROM products WHERE id = $product_id"); post_bug.cgi:181: if (!FetchOneColumn()) { post_bug.cgi:187: SendSQL("SELECT defaultmilestone FROM products WHERE name=$sql_product"); post_bug.cgi:188: $cgi->param(-name => 'target_milestone', -value => FetchOneColumn()); post_bug.cgi:281:SendSQL("SELECT NOW()"); post_bug.cgi:282:my $timestamp = FetchOneColumn(); post_bug.cgi:283:my $sql_timestamp = SqlQuote($timestamp); post_bug.cgi:293: $sql .= SqlQuote($cgi->param($field)) . ","; post_bug.cgi:310: $sql .= SqlQuote($est_time) . "," . SqlQuote($est_time) . ","; post_bug.cgi:317: $sql .= SqlQuote($cgi->param('deadline')); post_bug.cgi:339: SendSQL("SELECT user_id FROM user_group_map post_bug.cgi:343: my ($permit) = FetchSQLData(); post_bug.cgi:345: SendSQL("SELECT othercontrol FROM group_control_map post_bug.cgi:347: my ($othercontrol) = FetchSQLData(); post_bug.cgi:357:SendSQL("SELECT DISTINCT groups.id, groups.name, " . post_bug.cgi:362:while (MoreSQLData()) { post_bug.cgi:363: my ($id, $groupname, $membercontrol, $othercontrol ) = FetchSQLData(); post_bug.cgi:381:SendSQL($sql); post_bug.cgi:388: SendSQL("INSERT INTO bug_group_map (bug_id, group_id) post_bug.cgi:398:SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext, isprivate) post_bug.cgi:399: VALUES ($id, " . SqlQuote($user->id) . ", $sql_timestamp, " . post_bug.cgi:400: SqlQuote($comment) . ", $privacy)"); post_bug.cgi:404: SendSQL("INSERT INTO cc (bug_id, who) VALUES ($id, $ccid)"); post_bug.cgi:410: SendSQL("INSERT INTO keywords (bug_id, keywordid) post_bug.cgi:415: SendSQL("SELECT name FROM keyworddefs WHERE id IN ( " . post_bug.cgi:418: while (MoreSQLData()) { post_bug.cgi:419: push (@list, FetchOneColumn()); post_bug.cgi:421: SendSQL("UPDATE bugs SET delta_ts = $sql_timestamp," . post_bug.cgi:422: " keywords = " . SqlQuote(join(', ', @list)) . post_bug.cgi:430: SendSQL("INSERT INTO dependencies ($me, $target) values " .
Updated•19 years ago
|
Assignee: general → tiagoratto
Updated•19 years ago
|
Target Milestone: --- → Bugzilla 2.24
Comment 1•19 years ago
|
||
Attachment #203376 -
Flags: review?(LpSolit)
Comment 2•19 years ago
|
||
Comment on attachment 203376 [details] [diff] [review] Patch v2 >+my $sql_product = $cgi->param('product'); >+trick_taint($sql_product); >+ >+my $sql_component = $cgi->param('component'); >+trick_taint($sql_component); That's a big r-! We detaint values because we pass them to the SQL query using placeholders. In your patch, you insert them directly. Moreover, I see no reason to keep 'sql_' in the variable names. >+ my $sth = $dbh->prepare(qq{SELECT initialowner FROM components >+ WHERE id = ?}); >+ $sth->execute($component_id); >+ my ($result) = $sth->fetchrow_array; Combine them in a single line using $dbh->selectrow_array(). >+ ($qa_contact) = $dbh->selectrow_array(qq{ >+ SELECT initialqacontact >+ FROM components >+ WHERE id = ? }, undef,$component_id); Nit: add a whitespace after commas. >+ if (!$dbh->selectcol_arrayref(qq{SELECT votestoconfirm >+ FROM products >+ WHERE id = '$product_id'})) { I really don't like having SQL queries in tests. First do the query, save the result in a variable and then use this variable in the test. Moreover, use *placeholders* and stop using selectcol_arrayref() when selectrow_array() should be used! >+ my $query =qq{SELECT defaultmilestone >+ FROM products >+ WHERE name = ?}; >+ >+ my ($result) = $dbh->selectrow_array($query, undef, $sql_product); I prefer the query to be in selectrow_array() directly. If the product name is only used here, then that's the place where you should detaint its value. > if (defined $cgi->param('cc')) { > foreach my $person ($cgi->param('cc')) { >- next unless $person; Not only this change has nothing to do with your patch, but removing it is *wrong*, see bug 315969. > foreach my $field (@used_fields) { >+ my $value = $cgi->param($field); >+ trick_taint($value); >+ $query .= qq{'$value', }; > } Use placeholders >+$query .= q{?, ?, }; You use them here but not above?! >+ $query .= qq{'$est_time', '$est_time')}; ... >+ $query .= q{NULL}; NULL values are inserted using 'undef'. >+ my @result = $dbh->selectrow_array(q{ >+ SELECT othercontrol >+ FROM group_control_map >+ WHERE group_id = ? >+ AND product_id = ?}, undef, >+ $v,$product_id); >+ my ($othercontrol) = @result; Use $othercontrol directly >+my $sth = $dbh->prepare(q{ >+ SELECT DISTINCT groups.id, groups.name, >+ membercontrol, othercontrol, >+ description >+ FROM groups >+ LEFT JOIN group_control_map ON group_id = id >+ AND product_id = ? >+ WHERE isbuggroup != 0 >+ AND isactive != 0 >+ ORDER BY description}); >+$sth->execute($product_id); >+ >+while (my @result = $sth->fetchrow_array) { Use $dbh->selectall_arrayref() and then a foreach loop over results saved in the array. >+trick_taint($timestamp); No need to detaint $timestamp. This value comes from the DB. >+trick_taint($query); The query doesn't need to be detaint. Values passed to it have. >+$dbh->do($query, undef, $user->id, $timestamp); So only two values are inserted into the DB? ;) >+ $dbh->do(q{INSERT INTO bug_group_map (bug_id, group_id) >+ VALUES (?, ?)}, undef, $id, $grouptoadd); When more than one value are passed, please enclose them in parens. >+trick_taint($timestamp); Not only $timestamp has already been detainted, but you don't need to do it for the same reason as above. >+ $id,$user->id,$timestamp,$comment,$privacy); Add whitespaces after commas. >+ my @list = @{$dbh->selectcol_arrayref(q{SELECT name >+ FROM keyworddefs >+ WHERE id >+ IN (?)}, undef, >+ join(',',@keywordlist))}; Doesn't work. Using placeholders will enclose the whole list. This is the kind of mistakes which is easily detected when being tested. Moreover, write "WHERE id IN (foo)" on one line. >+ $dbh->do(q{UPDATE bugs >+ SET delta_ts = ?, >+ keywords = ? >+ WHERE bug_id = ?}, undef, $timestamp, >+ join(',',@list),$id); Parameters on one line when the list is not too long, which is the case here.
Attachment #203376 -
Flags: review?(LpSolit) → review-
Comment 3•19 years ago
|
||
Attachment #203376 -
Attachment is obsolete: true
Attachment #204697 -
Flags: review?(wicked)
Updated•19 years ago
|
Assignee: tiagoratto → create-and-change
Updated•19 years ago
|
Severity: normal → enhancement
Updated•19 years ago
|
Assignee: create-and-change → tiagoratto
Reporter | ||
Comment 4•19 years ago
|
||
Comment on attachment 204697 [details] [diff] [review] Patch v3 >+trick_taint($product); Move this before the if in line 216 so it's closer to where it's actually used. >+ ($qa_contact) = $dbh->selectrow_array(q{ >+ SELECT initialqacontact >+ FROM components >+ WHERE id = ? }, >+ undef, $component_id); Nit: No reason to format this differently than other similar SQL fragments (basicly, no new line after the q{ and no space after WHERE id = ?). >+my @fields_values; >+foreach my $field (@used_fields) { >+ if (defined $cgi->param($field)) { >+ my $value = $cgi->param($field); >+ trick_taint($value); >+ push (@fields_values, $value); >+ } >+} >+ Umm, I see no reason to have this here and confuse the logic. Combine this foreach with the one doing similar loop around line 357. >+my $query = qq{INSERT INTO bugs ($sql_used_fields, reporter, delta_ts, >+ estimated_time, remaining_time, >+ deadline) >+ VALUES ($sql_used_fields_values ?, ?, ?, ?, ? )}; Nit: No need to indent VALUES line or have newline before deadline. >+ $est_time = $cgi->param('estimated_time'); > Bugzilla::Bug::ValidateTime($est_time, 'estimated_time'); >- $sql .= SqlQuote($est_time) . "," . SqlQuote($est_time) . ","; Variable $est_time needs to be trick_tainted after ValidateTime is called. This is probably why post_bug.cgi crashes with: Insecure dependency in parameter 20 of DBI::db=HASH(0x9e9d594)->do method call while running with -T switch at post_bug.cgi line 459. >+ SELECT DISTINCT groups.id, groups.name, >+ membercontrol, othercontrol, >+ description Nit: No need to use three lines for these when there's room to combine. >+$dbh->do($query, undef, >+ (@fields_values, $user->id, $timestamp, $est_time, >+ $est_time, $deadline)); Use different variable for remaining time even though it will have same value as $est_time. Nit: No need to put newline after undef param. >+ $dbh->do(q{INSERT INTO bug_group_map (bug_id, group_id) >+ VALUES (?, ?)}, >+ undef, ($id, $grouptoadd)); Nit: No need to put VALUES on a separate line when there's room on the first line. >+$dbh->do(q{INSERT INTO longdescs >+ (bug_id, who, bug_when, thetext, isprivate) >+ VALUES (?, ?, ?, ?, ?)}, >+ undef, ($id, $user->id, $timestamp, $comment, $privacy)); Nit: Put second line with first and don't indent VALUES. >+ $dbh->do(q{INSERT INTO keywords (bug_id, keywordid) >+ VALUES (?, ?)}, >+ undef, ($id, $keyword)); Nit: Move VALUES line with the first line. >+ my $list = $dbh->selectcol_arrayref(q{ >+ SELECT name >+ FROM keyworddefs >+ WHERE id IN (}. >+ join(', ', @keywordlist).q{)}); Nit: No newline after q{ and add spaces around the dots. Also use normal quoting and not q{} around that lonely ). >+ $dbh->do(q{UPDATE bugs >+ SET delta_ts = ?, keywords = ? >+ WHERE bug_id = ?}, >+ undef, ($timestamp, join(', ', @$list), $id)); I don't think join() clause will work as a param. Move it inside the SQL fragment like it was in previous SELECT. Nit: Combine SET clause with the first line. >+ $dbh->do(qq{INSERT INTO dependencies ($me, $target) >+ VALUES (?, ?)}, undef, ($id, $i)); Nit: No need to intent VALUES line.
Attachment #204697 -
Flags: review?(wicked) → review-
Assignee | ||
Updated•19 years ago
|
Assignee: tiagoratto → gabriel
Assignee | ||
Comment 5•19 years ago
|
||
fixed version.
Attachment #204697 -
Attachment is obsolete: true
Attachment #216663 -
Flags: review?(wicked+bz)
Comment 6•18 years ago
|
||
Comment on attachment 216663 [details] [diff] [review] v4-diff >+my @fields_values; >+my $sql_used_fields_values = ""; >+foreach my $field (@fields_values) { Huh? you have to loop over @used_fields. >+ $sql_used_fields_values .= q{?, }; Instead of this hack, you could write: $sql_placeholders = "?, " x scalar(@used_fields); The "x" notation means appending "?, " scalar(@used_fields) times. Of course, this goes outside the loop. >+ if (defined $cgi->param($field)) { fields from @used_fields are *all* defined, by definition. >-$sql .= $user->id . ", $sql_timestamp, "; Instead of removing this line, you could push() these values into @fields_values. >+my $est_time; >+my $deadline; >+my $rem_time; $rem_time is useless as it will always be equal to $est_time. Remove it. Moreover, initialize these values in case you are not in the timetracking group: my $est_time = 0; > if (UserInGroup(Param("timetrackinggroup")) && > defined $cgi->param('estimated_time')) { > >+ $est_time = $cgi->param('estimated_time'); > Bugzilla::Bug::ValidateTime($est_time, 'estimated_time'); >+ $rem_time = $est_time; As said above, $rem_time is useless. > } else { >+ $est_time = 0; >+ $rem_time = 0; > } If you have correctly set the default value for $est_time, this ELSE block is useless. Moreover, you can now push() $est_time twice into @fields_values (outside the IF block, of course). > } else { >+ $deadline = undef; > } Here too, $deadline is already undefined when you are not in the timetracking group. Moreover, you can now push() it into @fields_values. > foreach my $b (grep(/^bit-\d*$/, $cgi->param())) { >+ my ($othercontrol) = $dbh->selectrow_array(q{ Prepare this SQL call outside the FOREACH loop. >+my $result = $dbh->selectall_arrayref(q{ >+ SELECT DISTINCT groups.id, groups.name, membercontrol, >+ othercontrol, description >+ FROM groups $groups (if not already in use) is more explicit than $result. >+ LEFT JOIN group_control_map ON group_id = id >+ AND product_id = ? Move ON group_id = id on its own line. >+foreach my $row (@$result) { Here too, $group is better than $row. >+$dbh->do($query, undef, (@fields_values, $user->id, $timestamp, >+ $est_time, $rem_time, $deadline)); If all additional values have been pushed in @fields_values, you now only have ($query, undef, @fields_values), which is more readable. > foreach my $grouptoadd (@groupstoadd) { >+ $dbh->do(q{INSERT INTO bug_group_map (bug_id, group_id) VALUES (?, ?)}, >+ undef, ($id, $grouptoadd)); > } Prepare it outside the FOREACH loop. > foreach my $ccid (keys(%ccids)) { >+ $dbh->do(q{INSERT INTO cc (bug_id, who) VALUES (?,?)}, >+ undef, ($id, $ccid)); > } Same comment here. > foreach my $keyword (@keywordlist) { >+ $dbh->do(q{INSERT INTO keywords (bug_id, keywordid) VALUES (?, ?)}, >+ undef, ($id, $keyword)); > } Same comment here. >+ $dbh->do(q{UPDATE bugs SET delta_ts = ?, keywords = } . join(', ', >+ @$list) . "WHERE bug_id = ?", undef, ($timestamp, $id)); And now we can open a security bug for SQL injection!!! join(', ', @$list) must be moved outside the query and you must use a placeholder instead: keywords = ? > foreach my $i (@{$deps{$target}}) { >+ $dbh->do(qq{INSERT INTO dependencies ($me, $target) >+ VALUES (?, ?)}, undef, ($id, $i)); Prepare it outside the FOREACH loop.
Attachment #216663 -
Flags: review?(wicked+bz) → review-
Assignee | ||
Comment 7•18 years ago
|
||
maybe the identation is not the best... :/
Attachment #216663 -
Attachment is obsolete: true
Attachment #217450 -
Flags: review?(LpSolit)
Comment 8•18 years ago
|
||
Comment on attachment 217450 [details] [diff] [review] v5-version >+ my $list = $dbh->selectcol_arrayref(q{ >+ SELECT name >+ FROM keyworddefs >+ WHERE id IN (?)}, undef, $kw_ids); You cannot use placeholders in IN(), because it will quote the whole list of keyword IDs, instead of quoting them one by one. You have to replace "?" by $kw_ids directly (this is a list of integers only, so there is no SQL injection possible here). This must be fixed on checkin. Else the patch works correctly. r=LpSolit
Attachment #217450 -
Flags: review?(LpSolit) → review+
Updated•18 years ago
|
Status: NEW → ASSIGNED
Flags: approval?
Updated•18 years ago
|
Flags: approval? → approval+
Comment 9•18 years ago
|
||
Checking in post_bug.cgi; /cvsroot/mozilla/webtools/bugzilla/post_bug.cgi,v <-- post_bug.cgi new revision: 1.142; previous revision: 1.141 done
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•