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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/search_engines/template_url_service.h" 5 #include "chrome/browser/search_engines/template_url_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 } 1528 }
1529 1529
1530 if (!template_url->sync_guid().empty()) 1530 if (!template_url->sync_guid().empty())
1531 guid_to_template_map_[template_url->sync_guid()] = template_url; 1531 guid_to_template_map_[template_url->sync_guid()] = template_url;
1532 if (loaded_) { 1532 if (loaded_) {
1533 UIThreadSearchTermsData search_terms_data(profile_); 1533 UIThreadSearchTermsData search_terms_data(profile_);
1534 provider_map_->Add(template_url, search_terms_data); 1534 provider_map_->Add(template_url, search_terms_data);
1535 } 1535 }
1536 } 1536 }
1537 1537
1538 void TemplateURLService::SetTemplateURLs(const TemplateURLVector& urls) { 1538 // Helper for partition() call in next function.
1539 // Add mappings for the new items. 1539 bool HasValidID(TemplateURL* t_url) {
1540 return t_url->id() != kInvalidTemplateURLID;
1541 }
1540 1542
1541 // First, add the items that already have id's, so that the next_id_ 1543 void TemplateURLService::SetTemplateURLs(TemplateURLVector* urls) {
1542 // gets properly set. 1544 // Partition the URLs first, instead of implementing the loops below by simply
1543 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); 1545 // scanning the input twice. While it's not supposed to happen normally, it's
1546 // possible for corrupt databases to return multiple entries with the same
1547 // keyword. In this case, the first loop may delete the first entry when
1548 // adding the second. If this happens, the second loop must not attempt to
1549 // access the deleted entry. Partitioning ensures this constraint.
1550 TemplateURLVector::iterator first_invalid(
1551 std::partition(urls->begin(), urls->end(), HasValidID));
beaudoin 2013/09/14 03:24:03 Clever use of partition!
1552
1553 // First, add the items that already have id's, so that the next_id_ gets
1554 // properly set.
1555 for (TemplateURLVector::const_iterator i = urls->begin(); i != first_invalid;
1544 ++i) { 1556 ++i) {
1545 if ((*i)->id() != kInvalidTemplateURLID) { 1557 next_id_ = std::max(next_id_, (*i)->id());
1546 next_id_ = std::max(next_id_, (*i)->id()); 1558 AddNoNotify(*i, false);
1547 AddNoNotify(*i, false);
1548 }
1549 } 1559 }
1550 1560
1551 // Next add the new items that don't have id's. 1561 // Next add the new items that don't have id's.
1552 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); 1562 for (TemplateURLVector::const_iterator i = first_invalid; i != urls->end();
1553 ++i) { 1563 ++i)
1554 if ((*i)->id() == kInvalidTemplateURLID) 1564 AddNoNotify(*i, true);
1555 AddNoNotify(*i, true); 1565
1556 } 1566 // Clear the input vector to reduce the chance callers will try to use a
1567 // (possibly deleted) entry.
1568 urls->clear();
1557 } 1569 }
1558 1570
1559 void TemplateURLService::ChangeToLoadedState() { 1571 void TemplateURLService::ChangeToLoadedState() {
1560 DCHECK(!loaded_); 1572 DCHECK(!loaded_);
1561 1573
1562 UIThreadSearchTermsData search_terms_data(profile_); 1574 UIThreadSearchTermsData search_terms_data(profile_);
1563 provider_map_->Init(template_urls_, search_terms_data); 1575 provider_map_->Init(template_urls_, search_terms_data);
1564 loaded_ = true; 1576 loaded_ = true;
1565 } 1577 }
1566 1578
(...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after
2526 2538
2527 // Remove entries that were created because of policy as they may have 2539 // Remove entries that were created because of policy as they may have
2528 // changed since the database was saved. 2540 // changed since the database was saved.
2529 RemoveProvidersCreatedByPolicy(template_urls, 2541 RemoveProvidersCreatedByPolicy(template_urls,
2530 &default_search_provider, 2542 &default_search_provider,
2531 default_from_prefs.get()); 2543 default_from_prefs.get());
2532 2544
2533 PatchMissingSyncGUIDs(template_urls); 2545 PatchMissingSyncGUIDs(template_urls);
2534 2546
2535 if (is_default_search_managed_) { 2547 if (is_default_search_managed_) {
2536 SetTemplateURLs(*template_urls); 2548 SetTemplateURLs(template_urls);
2537 2549
2538 if (TemplateURLsHaveSamePrefs(default_search_provider, 2550 if (TemplateURLsHaveSamePrefs(default_search_provider,
2539 default_from_prefs.get())) { 2551 default_from_prefs.get())) {
2540 // The value from the preferences was previously stored in the database. 2552 // The value from the preferences was previously stored in the database.
2541 // Reuse it. 2553 // Reuse it.
2542 } else { 2554 } else {
2543 // The value from the preferences takes over. 2555 // The value from the preferences takes over.
2544 default_search_provider = NULL; 2556 default_search_provider = NULL;
2545 if (default_from_prefs.get()) { 2557 if (default_from_prefs.get()) {
2546 TemplateURLData data(default_from_prefs->data()); 2558 TemplateURLData data(default_from_prefs->data());
(...skipping 27 matching lines...) Expand all
2574 } 2586 }
2575 2587
2576 // If the default search provider existed previously, then just 2588 // If the default search provider existed previously, then just
2577 // set the member variable. Otherwise, we'll set it using the method 2589 // set the member variable. Otherwise, we'll set it using the method
2578 // to ensure that it is saved properly after its id is set. 2590 // to ensure that it is saved properly after its id is set.
2579 if (default_search_provider && 2591 if (default_search_provider &&
2580 (default_search_provider->id() != kInvalidTemplateURLID)) { 2592 (default_search_provider->id() != kInvalidTemplateURLID)) {
2581 default_search_provider_ = default_search_provider; 2593 default_search_provider_ = default_search_provider;
2582 default_search_provider = NULL; 2594 default_search_provider = NULL;
2583 } 2595 }
2584 SetTemplateURLs(*template_urls); 2596 SetTemplateURLs(template_urls);
2585 2597
2586 if (default_search_provider) { 2598 if (default_search_provider) {
2587 // Note that this saves the default search provider to prefs. 2599 // Note that this saves the default search provider to prefs.
2588 SetDefaultSearchProvider(default_search_provider); 2600 SetDefaultSearchProvider(default_search_provider);
2589 } else { 2601 } else {
2590 // Always save the default search provider to prefs. That way we don't 2602 // Always save the default search provider to prefs. That way we don't
2591 // have to worry about it being out of sync. 2603 // have to worry about it being out of sync.
2592 if (default_search_provider_) 2604 if (default_search_provider_)
2593 SaveDefaultSearchProviderToPrefs(default_search_provider_); 2605 SaveDefaultSearchProviderToPrefs(default_search_provider_);
2594 } 2606 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 const ExtensionKeyword& extension_keyword) const { 2638 const ExtensionKeyword& extension_keyword) const {
2627 TemplateURLData data; 2639 TemplateURLData data;
2628 data.short_name = UTF8ToUTF16(extension_keyword.extension_name); 2640 data.short_name = UTF8ToUTF16(extension_keyword.extension_name);
2629 data.SetKeyword(UTF8ToUTF16(extension_keyword.extension_keyword)); 2641 data.SetKeyword(UTF8ToUTF16(extension_keyword.extension_keyword));
2630 // This URL is not actually used for navigation. It holds the extension's 2642 // This URL is not actually used for navigation. It holds the extension's
2631 // ID, as well as forcing the TemplateURL to be treated as a search keyword. 2643 // ID, as well as forcing the TemplateURL to be treated as a search keyword.
2632 data.SetURL(std::string(extensions::kExtensionScheme) + "://" + 2644 data.SetURL(std::string(extensions::kExtensionScheme) + "://" +
2633 extension_keyword.extension_id + "/?q={searchTerms}"); 2645 extension_keyword.extension_id + "/?q={searchTerms}");
2634 return new TemplateURL(profile_, data); 2646 return new TemplateURL(profile_, data);
2635 } 2647 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698