Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Unified Diff: chrome/browser/search_engines/template_url_service.cc

Issue 23536053: Fix read-after-free when loading two search engines with the same keyword. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/search_engines/template_url_service.cc
===================================================================
--- chrome/browser/search_engines/template_url_service.cc (revision 222964)
+++ chrome/browser/search_engines/template_url_service.cc (working copy)
@@ -1535,25 +1535,37 @@
}
}
-void TemplateURLService::SetTemplateURLs(const TemplateURLVector& urls) {
- // Add mappings for the new items.
+// Helper for partition() call in next function.
+bool HasValidID(TemplateURL* t_url) {
+ return t_url->id() != kInvalidTemplateURLID;
+}
- // First, add the items that already have id's, so that the next_id_
- // gets properly set.
- for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end();
+void TemplateURLService::SetTemplateURLs(TemplateURLVector* urls) {
+ // Partition the URLs first, instead of implementing the loops below by simply
+ // scanning the input twice. While it's not supposed to happen normally, it's
+ // possible for corrupt databases to return multiple entries with the same
+ // keyword. In this case, the first loop may delete the first entry when
+ // adding the second. If this happens, the second loop must not attempt to
+ // access the deleted entry. Partitioning ensures this constraint.
+ TemplateURLVector::iterator first_invalid(
+ std::partition(urls->begin(), urls->end(), HasValidID));
beaudoin 2013/09/14 03:24:03 Clever use of partition!
+
+ // First, add the items that already have id's, so that the next_id_ gets
+ // properly set.
+ for (TemplateURLVector::const_iterator i = urls->begin(); i != first_invalid;
++i) {
- if ((*i)->id() != kInvalidTemplateURLID) {
- next_id_ = std::max(next_id_, (*i)->id());
- AddNoNotify(*i, false);
- }
+ next_id_ = std::max(next_id_, (*i)->id());
+ AddNoNotify(*i, false);
}
// Next add the new items that don't have id's.
- for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end();
- ++i) {
- if ((*i)->id() == kInvalidTemplateURLID)
- AddNoNotify(*i, true);
- }
+ for (TemplateURLVector::const_iterator i = first_invalid; i != urls->end();
+ ++i)
+ AddNoNotify(*i, true);
+
+ // Clear the input vector to reduce the chance callers will try to use a
+ // (possibly deleted) entry.
+ urls->clear();
}
void TemplateURLService::ChangeToLoadedState() {
@@ -2533,7 +2545,7 @@
PatchMissingSyncGUIDs(template_urls);
if (is_default_search_managed_) {
- SetTemplateURLs(*template_urls);
+ SetTemplateURLs(template_urls);
if (TemplateURLsHaveSamePrefs(default_search_provider,
default_from_prefs.get())) {
@@ -2581,7 +2593,7 @@
default_search_provider_ = default_search_provider;
default_search_provider = NULL;
}
- SetTemplateURLs(*template_urls);
+ SetTemplateURLs(template_urls);
if (default_search_provider) {
// Note that this saves the default search provider to prefs.

Powered by Google App Engine
This is Rietveld 408576698