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

Unified Diff: chrome/browser/password_manager/password_store_mac.cc

Issue 825773003: PasswordStore: Use ScopedVector to express ownership of forms (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix one more use-after-free Created 5 years, 11 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/password_manager/password_store_mac.cc
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc
index bb50c7425f1a6208bdb54b9f42369294e273602c..e056c462c1f3f206504d2dea253422548bd1db56 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -15,7 +15,6 @@
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h"
-#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -189,6 +188,13 @@ PasswordStoreChangeList FormsToRemoveChangeList(
return changes;
}
+// Moves the content of |second| to the end of |first|.
+void AppendSecondToFirst(ScopedVector<autofill::PasswordForm>* first,
+ ScopedVector<autofill::PasswordForm>* second) {
+ first->insert(first->end(), second->begin(), second->end());
+ second->weak_clear();
+}
+
} // namespace
#pragma mark -
@@ -418,70 +424,62 @@ PasswordForm* BestKeychainFormForForm(
return partial_match;
}
-// Returns entries from |forms| that are blacklist entries, after removing
-// them from |forms|.
-std::vector<PasswordForm*> ExtractBlacklistForms(
- std::vector<PasswordForm*>* forms) {
- std::vector<PasswordForm*> blacklist_forms;
- for (std::vector<PasswordForm*>::iterator i = forms->begin();
- i != forms->end();) {
- PasswordForm* form = *i;
- if (form->blacklisted_by_user) {
- blacklist_forms.push_back(form);
- i = forms->erase(i);
- } else {
- ++i;
- }
- }
- return blacklist_forms;
-}
-
-// Deletes and removes from v any element that exists in s.
-template <class T>
-void DeleteVectorElementsInSet(std::vector<T*>* v, const std::set<T*>& s) {
- for (typename std::vector<T*>::iterator i = v->begin(); i != v->end();) {
- T* element = *i;
- if (s.find(element) != s.end()) {
- delete element;
- i = v->erase(i);
- } else {
- ++i;
- }
+// Moves entries from |forms| that are blacklist entries into |blacklist|.
+void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms,
+ ScopedVector<autofill::PasswordForm>* blacklist) {
+ blacklist->reserve(blacklist->size() + forms->size());
+ ScopedVector<autofill::PasswordForm> non_blacklist;
+ for (auto& form : *forms) {
+ if (form->blacklisted_by_user)
+ blacklist->push_back(form);
+ else
+ non_blacklist.push_back(form);
+ form = nullptr;
}
+ forms->swap(non_blacklist);
}
-void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms,
- std::vector<PasswordForm*>* database_forms,
- std::vector<PasswordForm*>* merged_forms) {
+// Takes |keychain_forms| and |database_forms| and moves the following 2 types
+// of forms to |merged_forms|: (1) blacklisted |database_forms|, (2)
+// |database_forms| which have a corresponding entry in |keychain_forms|. The
+// database forms of type (2) have their password value updated from the
+// corresponding keychain form, and all the keychain forms corresponding to some
+// database form are removed from |keychain_forms| and deleted.
+void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms,
+ ScopedVector<autofill::PasswordForm>* database_forms,
+ ScopedVector<autofill::PasswordForm>* merged_forms) {
// Pull out the database blacklist items, since they are used as-is rather
// than being merged with keychain forms.
- std::vector<PasswordForm*> database_blacklist_forms =
- ExtractBlacklistForms(database_forms);
+ ExtractBlacklistForms(database_forms, merged_forms);
// Merge the normal entries.
- std::set<PasswordForm*> used_keychain_forms;
- for (std::vector<PasswordForm*>::iterator i = database_forms->begin();
- i != database_forms->end();) {
- PasswordForm* db_form = *i;
- PasswordForm* best_match = BestKeychainFormForForm(*db_form,
- keychain_forms);
+ ScopedVector<autofill::PasswordForm> unused_database_forms;
+ unused_database_forms.reserve(database_forms->size());
+ std::set<autofill::PasswordForm*> used_keychain_forms;
+ for (auto& db_form : *database_forms) {
+ PasswordForm* best_match =
+ BestKeychainFormForForm(*db_form, &keychain_forms->get());
if (best_match) {
used_keychain_forms.insert(best_match);
db_form->password_value = best_match->password_value;
merged_forms->push_back(db_form);
- i = database_forms->erase(i);
} else {
- ++i;
+ unused_database_forms.push_back(db_form);
}
+ db_form = nullptr;
}
-
- // Add in the blacklist entries from the database.
- merged_forms->insert(merged_forms->end(),
- database_blacklist_forms.begin(),
- database_blacklist_forms.end());
+ database_forms->swap(unused_database_forms);
// Clear out all the Keychain entries we used.
- DeleteVectorElementsInSet(keychain_forms, used_keychain_forms);
+ ScopedVector<autofill::PasswordForm> unused_keychain_forms;
+ unused_keychain_forms.reserve(keychain_forms->size());
+ for (auto& keychain_form : *keychain_forms) {
+ if (!ContainsKey(used_keychain_forms, keychain_form)) {
+ unused_keychain_forms.push_back(keychain_form);
+ keychain_form = nullptr;
+ }
+ }
+ keychain_forms->swap(unused_keychain_forms);
}
std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms(
@@ -504,9 +502,9 @@ std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms(
return item_form_pairs;
}
-std::vector<PasswordForm*> GetPasswordsForForms(
- const AppleKeychain& keychain,
- std::vector<PasswordForm*>* database_forms) {
+void GetPasswordsForForms(const AppleKeychain& keychain,
+ ScopedVector<autofill::PasswordForm>* database_forms,
+ ScopedVector<autofill::PasswordForm>* passwords) {
// First load the attributes of all items in the keychain without loading
// their password data, and then match items in |database_forms| against them.
// This avoids individually searching through the keychain for passwords
@@ -522,29 +520,27 @@ std::vector<PasswordForm*> GetPasswordsForForms(
// Next, compare the attributes of the PasswordForms in |database_forms|
// against those in |item_form_pairs|, and extract password data for each
// matching PasswordForm using its corresponding SecKeychainItemRef.
- std::vector<PasswordForm*> merged_forms;
- for (std::vector<PasswordForm*>::iterator i = database_forms->begin();
- i != database_forms->end();) {
- std::vector<PasswordForm*> db_form_container(1, *i);
- std::vector<PasswordForm*> keychain_matches =
- ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, **i);
- MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms);
- if (db_form_container.empty()) {
- i = database_forms->erase(i);
- } else {
- ++i;
- }
- STLDeleteElements(&keychain_matches);
+ ScopedVector<autofill::PasswordForm> unused_db_forms;
+ unused_db_forms.reserve(database_forms->size());
+ for (auto& db_form : *database_forms) {
+ ScopedVector<autofill::PasswordForm> keychain_matches(
vasilii 2015/01/28 15:09:03 nit: ScopedVector<autofill::PasswordForm> keychain
vabr (Chromium) 2015/01/28 16:36:27 Done. You are right: Both the r-value constructor
vasilii 2015/01/28 17:27:22 There is no operator= here. "MyObject o = somethin
+ ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *db_form));
+
+ ScopedVector<autofill::PasswordForm> db_form_container;
+ db_form_container.push_back(db_form);
+ db_form = nullptr;
+ MergePasswordForms(&keychain_matches, &db_form_container, passwords);
+ unused_db_forms.insert(unused_db_forms.end(), db_form_container.begin(),
+ db_form_container.end());
+ db_form_container.weak_clear();
}
+ database_forms->swap(unused_db_forms);
- // Clean up temporary PasswordForms and SecKeychainItemRefs.
STLDeleteContainerPairSecondPointers(item_form_pairs.begin(),
item_form_pairs.end());
- for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin();
- i != keychain_items.end(); ++i) {
- keychain.Free(*i);
+ for (SecKeychainItemRef item : keychain_items) {
+ keychain.Free(item);
}
- return merged_forms;
}
// TODO(stuartmorgan): signon_realm for proxies is not yet supported.
@@ -590,11 +586,11 @@ bool FormIsValidAndMatchesOtherForm(const PasswordForm& query_form,
query_form, other_form, STRICT_FORM_MATCH);
}
-std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm(
+ScopedVector<autofill::PasswordForm> ExtractPasswordsMergeableWithForm(
const AppleKeychain& keychain,
const std::vector<ItemFormPair>& item_form_pairs,
const PasswordForm& query_form) {
- std::vector<PasswordForm*> matches;
+ ScopedVector<autofill::PasswordForm> matches;
for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin();
i != item_form_pairs.end(); ++i) {
if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) {
@@ -602,16 +598,14 @@ std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm(
// returned forms.
scoped_ptr<PasswordForm> form_with_password(new PasswordForm());
internal_keychain_helpers::FillPasswordFormFromKeychainItem(
- keychain,
- *(i->first),
- form_with_password.get(),
+ keychain, *(i->first), form_with_password.get(),
true); // Load password attributes and data.
// Do not include blacklisted items found in the keychain.
if (!form_with_password->blacklisted_by_user)
matches.push_back(form_with_password.release());
}
}
- return matches;
+ return matches.Pass();
}
} // namespace internal_keychain_helpers
@@ -623,12 +617,12 @@ MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter(
: keychain_(keychain), finds_only_owned_(false) {
}
-std::vector<PasswordForm*> MacKeychainPasswordFormAdapter::PasswordsFillingForm(
+ScopedVector<autofill::PasswordForm>
+MacKeychainPasswordFormAdapter::PasswordsFillingForm(
const std::string& signon_realm,
PasswordForm::Scheme scheme) {
std::vector<SecKeychainItemRef> keychain_items =
MatchingKeychainItems(signon_realm, scheme, NULL, NULL);
-
return ConvertKeychainItemsToForms(&keychain_items);
}
@@ -681,8 +675,8 @@ std::vector<SecKeychainItemRef>
return matches;
}
-std::vector<PasswordForm*>
- MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() {
+ScopedVector<autofill::PasswordForm>
+MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() {
std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems();
return ConvertKeychainItemsToForms(&items);
}
@@ -745,21 +739,20 @@ void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems(
finds_only_owned_ = finds_only_owned;
}
-std::vector<PasswordForm*>
- MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms(
- std::vector<SecKeychainItemRef>* items) {
- std::vector<PasswordForm*> keychain_forms;
- for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin();
- i != items->end(); ++i) {
- PasswordForm* form = new PasswordForm();
+ScopedVector<autofill::PasswordForm>
+MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms(
+ std::vector<SecKeychainItemRef>* items) {
+ ScopedVector<autofill::PasswordForm> forms;
+ for (SecKeychainItemRef item : *items) {
+ scoped_ptr<PasswordForm> form(new PasswordForm());
if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(
- *keychain_, *i, form, true)) {
- keychain_forms.push_back(form);
+ *keychain_, item, form.get(), true)) {
+ forms.push_back(form.release());
}
- keychain_->Free(*i);
+ keychain_->Free(item);
}
items->clear();
- return keychain_forms;
+ return forms.Pass();
}
SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm(
@@ -983,15 +976,15 @@ PasswordStoreChangeList PasswordStoreMac::RemoveLoginsCreatedBetweenImpl(
base::Time delete_begin,
base::Time delete_end) {
PasswordStoreChangeList changes;
- ScopedVector<PasswordForm> forms;
+ ScopedVector<PasswordForm> forms_to_remove;
if (login_metadata_db_ &&
login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end,
- &forms.get()) &&
+ &forms_to_remove) &&
login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin,
delete_end)) {
- RemoveKeychainForms(forms.get());
- CleanOrphanedForms(&forms.get());
- changes = FormsToRemoveChangeList(forms.get());
+ RemoveKeychainForms(forms_to_remove.get());
+ CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms.
+ changes = FormsToRemoveChangeList(forms_to_remove.get());
LogStatsForBulkDeletion(changes.size());
}
return changes;
@@ -1001,14 +994,14 @@ PasswordStoreChangeList PasswordStoreMac::RemoveLoginsSyncedBetweenImpl(
base::Time delete_begin,
base::Time delete_end) {
PasswordStoreChangeList changes;
- ScopedVector<PasswordForm> forms;
+ ScopedVector<PasswordForm> forms_to_remove;
if (login_metadata_db_ &&
login_metadata_db_->GetLoginsSyncedBetween(delete_begin, delete_end,
- &forms.get()) &&
+ &forms_to_remove) &&
login_metadata_db_->RemoveLoginsSyncedBetween(delete_begin, delete_end)) {
- RemoveKeychainForms(forms.get());
- CleanOrphanedForms(&forms.get());
- changes = FormsToRemoveChangeList(forms.get());
+ RemoveKeychainForms(forms_to_remove.get());
+ CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms_to_remove.
+ changes = FormsToRemoveChangeList(forms_to_remove.get());
LogStatsForBulkDeletionDuringRollback(changes.size());
}
return changes;
@@ -1022,97 +1015,92 @@ void PasswordStoreMac::GetLoginsImpl(
prompt_policy == ALLOW_PROMPT);
if (!login_metadata_db_) {
- callback_runner.Run(std::vector<PasswordForm*>());
+ callback_runner.Run(ScopedVector<autofill::PasswordForm>());
return;
}
ScopedVector<PasswordForm> database_forms;
- login_metadata_db_->GetLogins(form, &database_forms.get());
+ login_metadata_db_->GetLogins(form, &database_forms);
// Let's gather all signon realms we want to match with keychain entries.
std::set<std::string> realm_set;
realm_set.insert(form.signon_realm);
- for (std::vector<PasswordForm*>::const_iterator db_form =
- database_forms.begin();
- db_form != database_forms.end();
- ++db_form) {
+ for (const autofill::PasswordForm* db_form : database_forms) {
// TODO(vabr): We should not be getting different schemes here.
// http://crbug.com/340112
- if (form.scheme != (*db_form)->scheme)
+ if (form.scheme != db_form->scheme)
continue; // Forms with different schemes never match.
- const std::string& original_singon_realm((*db_form)->original_signon_realm);
+ const std::string& original_singon_realm(db_form->original_signon_realm);
if (!original_singon_realm.empty())
realm_set.insert(original_singon_realm);
}
- std::vector<PasswordForm*> keychain_forms;
+ ScopedVector<autofill::PasswordForm> keychain_forms;
for (std::set<std::string>::const_iterator realm = realm_set.begin();
- realm != realm_set.end();
- ++realm) {
+ realm != realm_set.end(); ++realm) {
MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get());
- std::vector<PasswordForm*> temp_keychain_forms =
- keychain_adapter.PasswordsFillingForm(*realm, form.scheme);
- keychain_forms.insert(keychain_forms.end(),
- temp_keychain_forms.begin(),
- temp_keychain_forms.end());
+ ScopedVector<autofill::PasswordForm> temp_keychain_forms(
+ keychain_adapter.PasswordsFillingForm(*realm, form.scheme));
+ AppendSecondToFirst(&keychain_forms, &temp_keychain_forms);
}
- std::vector<PasswordForm*> matched_forms;
- internal_keychain_helpers::MergePasswordForms(&keychain_forms,
- &database_forms.get(),
- &matched_forms);
+ ScopedVector<autofill::PasswordForm> matched_forms;
+ internal_keychain_helpers::MergePasswordForms(
+ &keychain_forms, &database_forms, &matched_forms);
// Strip any blacklist entries out of the unused Keychain array, then take
// all the entries that are left (which we can use as imported passwords).
ScopedVector<PasswordForm> keychain_blacklist_forms;
- internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms).swap(
- keychain_blacklist_forms.get());
+ internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms,
+ &keychain_blacklist_forms);
matched_forms.insert(matched_forms.end(),
keychain_forms.begin(),
keychain_forms.end());
- keychain_forms.clear();
+ keychain_forms.weak_clear();
if (!database_forms.empty()) {
RemoveDatabaseForms(database_forms.get());
NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get()));
}
- callback_runner.Run(matched_forms);
+ callback_runner.Run(matched_forms.Pass());
}
void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
- FillBlacklistLogins(request->result());
+ ScopedVector<autofill::PasswordForm> obtained_forms;
+ FillBlacklistLogins(&obtained_forms);
+ request->result()->swap(obtained_forms.get());
ForwardLoginsResult(request);
}
void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) {
- FillAutofillableLogins(request->result());
+ ScopedVector<autofill::PasswordForm> obtained_forms;
+ FillAutofillableLogins(&obtained_forms);
+ request->result()->swap(obtained_forms.get());
ForwardLoginsResult(request);
}
bool PasswordStoreMac::FillAutofillableLogins(
- std::vector<PasswordForm*>* forms) {
+ ScopedVector<autofill::PasswordForm>* forms) {
DCHECK(thread_->message_loop() == base::MessageLoop::current());
ScopedVector<PasswordForm> database_forms;
if (!login_metadata_db_ ||
- !login_metadata_db_->GetAutofillableLogins(&database_forms.get()))
+ !login_metadata_db_->GetAutofillableLogins(&database_forms))
return false;
- std::vector<PasswordForm*> merged_forms =
- internal_keychain_helpers::GetPasswordsForForms(*keychain_,
- &database_forms.get());
+ internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms,
+ forms);
if (!database_forms.empty()) {
RemoveDatabaseForms(database_forms.get());
NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get()));
}
- forms->insert(forms->end(), merged_forms.begin(), merged_forms.end());
return true;
}
bool PasswordStoreMac::FillBlacklistLogins(
- std::vector<PasswordForm*>* forms) {
+ ScopedVector<autofill::PasswordForm>* forms) {
DCHECK(thread_->message_loop() == base::MessageLoop::current());
return login_metadata_db_ && login_metadata_db_->GetBlacklistLogins(forms);
}
@@ -1129,21 +1117,19 @@ bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm(
const autofill::PasswordForm& form) {
DCHECK(login_metadata_db_);
bool has_match = false;
- std::vector<PasswordForm*> database_forms;
+ ScopedVector<autofill::PasswordForm> database_forms;
login_metadata_db_->GetLogins(form, &database_forms);
- for (std::vector<PasswordForm*>::iterator i = database_forms.begin();
- i != database_forms.end(); ++i) {
+ for (const autofill::PasswordForm* db_form : database_forms) {
// Below we filter out forms with non-empty original_signon_realm, because
// those signal fuzzy matches, and we are only interested in exact ones.
- if ((*i)->original_signon_realm.empty() &&
+ if (db_form->original_signon_realm.empty() &&
internal_keychain_helpers::FormsMatchForMerge(
- form, **i, internal_keychain_helpers::STRICT_FORM_MATCH) &&
- (*i)->origin == form.origin) {
+ form, *db_form, internal_keychain_helpers::STRICT_FORM_MATCH) &&
+ db_form->origin == form.origin) {
has_match = true;
break;
}
}
- STLDeleteElements(&database_forms);
return has_match;
}
@@ -1166,19 +1152,24 @@ void PasswordStoreMac::RemoveKeychainForms(
}
}
-void PasswordStoreMac::CleanOrphanedForms(std::vector<PasswordForm*>* forms) {
- DCHECK(forms);
+void PasswordStoreMac::CleanOrphanedForms(
+ ScopedVector<autofill::PasswordForm>* orphaned_forms) {
+ DCHECK(orphaned_forms);
DCHECK(login_metadata_db_);
- std::vector<PasswordForm*> database_forms;
+ ScopedVector<autofill::PasswordForm> database_forms;
login_metadata_db_->GetAutofillableLogins(&database_forms);
- ScopedVector<PasswordForm> merged_forms;
- merged_forms.get() = internal_keychain_helpers::GetPasswordsForForms(
- *keychain_, &database_forms);
+ // Filter forms with corresponding Keychain entry out of |database_forms|.
+ ScopedVector<PasswordForm> forms_with_keychain_entry;
+ internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms,
+ &forms_with_keychain_entry);
// Clean up any orphaned database entries.
- RemoveDatabaseForms(database_forms);
+ RemoveDatabaseForms(database_forms.get());
- forms->insert(forms->end(), database_forms.begin(), database_forms.end());
+ // Move the orphaned DB forms to the output parameter.
+ orphaned_forms->insert(orphaned_forms->end(), database_forms.begin(),
+ database_forms.end());
+ database_forms.weak_clear();
}

Powered by Google App Engine
This is Rietveld 408576698