# # # patch "ChangeLog" # from [fda6a7b382f9cfe4050597e6169746f84afbce25] # to [5d9e0acf1f11effa5a3ac2f85b5c78c13f8bd0c8] # # patch "database.cc" # from [241842d74b2d914cb261c24db82faa8b1203da17] # to [a5e4bb8071e7d5980ead69694c9c0c45aa8d1541] # ============================================================ --- ChangeLog fda6a7b382f9cfe4050597e6169746f84afbce25 +++ ChangeLog 5d9e0acf1f11effa5a3ac2f85b5c78c13f8bd0c8 @@ -1,3 +1,11 @@ +2006-04-28 Matthew Gregan
+ + * database.cc (query::query): Allow query to be constructed + without an initial SQL command. + * database.cc (database::complete): Replace use of boost::format + with query; building the query.sql_cmd as we go. Fixes potential + SQL injection attacks. + 2006-04-28 Alex Queiroz * po/pt_BR.po: Translated even more strings. ============================================================ --- database.cc 241842d74b2d914cb261c24db82faa8b1203da17 +++ database.cc a5e4bb8071e7d5980ead69694c9c0c45aa8d1541 @@ -96,9 +96,12 @@ struct query { - query(std::string const & cmd) + explicit query(std::string const & cmd) : sql_cmd(cmd) {} + + query() + {} query & operator %(query_param const & qp) { @@ -2262,10 +2265,11 @@ // limit. this is done by building an SQL select statement for each term // in the limit and then INTERSECTing them all. - string lim = "("; + query lim; + lim.sql_cmd = "("; if (limit.empty()) { - lim += "SELECT id FROM revision_certs"; + lim.sql_cmd += "SELECT id FROM revision_certs"; } else { @@ -2276,13 +2280,12 @@ if (first_limit) first_limit = false; else - lim += " INTERSECT "; + lim.sql_cmd += " INTERSECT "; if (i->first == selectors::sel_ident) { - lim += "SELECT id FROM revision_certs "; - lim += (boost::format("WHERE id GLOB '%s*'") - % i->second).str(); + lim.sql_cmd += "SELECT id FROM revision_certs WHERE id GLOB ?"; + lim % text(i->second + "*"); } else if (i->first == selectors::sel_cert) { @@ -2298,28 +2301,23 @@ certname = i->second.substr(0, spot); spot++; certvalue = i->second.substr(spot); - lim += "SELECT id FROM revision_certs "; - lim += (boost::format("WHERE name='%s' AND CAST(value AS TEXT) glob '%s'") - % certname % certvalue).str(); + lim.sql_cmd += "SELECT id FROM revision_certs WHERE name=? AND CAST(value AS TEXT) glob ?"; + lim % text(certname) % text(certvalue); } else { - lim += "SELECT id FROM revision_certs "; - lim += (boost::format("WHERE name='%s'") - % i->second).str(); + lim.sql_cmd += "SELECT id FROM revision_certs WHERE name=?"; + lim % text(i->second); } } } else if (i->first == selectors::sel_unknown) { - lim += "SELECT id FROM revision_certs "; - lim += (boost::format(" WHERE (name='%s' OR name='%s' OR name='%s')") - % author_cert_name - % tag_cert_name - % branch_cert_name).str(); - lim += (boost::format(" AND CAST(value AS TEXT) glob '*%s*'") - % i->second).str(); + lim.sql_cmd += "SELECT id FROM revision_certs WHERE (name=? OR name=? OR name=?)"; + lim % text(author_cert_name) % text(tag_cert_name) % text(branch_cert_name); + lim.sql_cmd += " AND CAST(value AS TEXT) glob ?"; + lim % text(i->second + "*"); } else if (i->first == selectors::sel_head) { @@ -2332,10 +2330,10 @@ } else { - string subquery = (boost::format("SELECT DISTINCT value FROM revision_certs WHERE name='%s' and CAST(value AS TEXT) glob '%s'") - % branch_cert_name % i->second).str(); + query subquery("SELECT DISTINCT value FROM revision_certs WHERE name=? AND CAST(value AS TEXT) glob ?"); + subquery % text(branch_cert_name) % text(i->second); results res; - fetch(res, one_col, any_rows, query(subquery)); + fetch(res, one_col, any_rows, subquery); for (size_t i = 0; i < res.size(); ++i) { data row_decoded(res[i][0]); @@ -2353,19 +2351,21 @@ L(FL("after get_branch_heads for %s, heads has %d entries\n") % (*bn) % heads.size()); } - lim += "SELECT id FROM revision_certs WHERE id IN ("; + lim.sql_cmd += "SELECT id FROM revision_certs WHERE id IN ("; if (heads.size()) { set