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

Side by Side Diff: components/sync/syncable/mutable_entry.cc

Issue 2844333003: [Sync] Address use-after-free in Directory::InsertEntry (Closed)
Patch Set: Created 3 years, 7 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
« no previous file with comments | « components/sync/syncable/mutable_entry.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 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 "components/sync/syncable/mutable_entry.h" 5 #include "components/sync/syncable/mutable_entry.h"
6 6
7 #include <memory> 7 #include <utility>
8 8
9 #include "components/sync/base/hash_util.h" 9 #include "components/sync/base/hash_util.h"
10 #include "components/sync/base/unique_position.h" 10 #include "components/sync/base/unique_position.h"
11 #include "components/sync/syncable/directory.h" 11 #include "components/sync/syncable/directory.h"
12 #include "components/sync/syncable/scoped_kernel_lock.h" 12 #include "components/sync/syncable/scoped_kernel_lock.h"
13 #include "components/sync/syncable/scoped_parent_child_index_updater.h" 13 #include "components/sync/syncable/scoped_parent_child_index_updater.h"
14 #include "components/sync/syncable/syncable_changes_version.h" 14 #include "components/sync/syncable/syncable_changes_version.h"
15 #include "components/sync/syncable/syncable_write_transaction.h" 15 #include "components/sync/syncable/syncable_write_transaction.h"
16 16
17 using std::string; 17 using std::string;
18 18
19 namespace syncer { 19 namespace syncer {
20 namespace syncable { 20 namespace syncable {
21 21
22 void MutableEntry::Init(WriteTransaction* trans,
23 ModelType model_type,
24 const Id& parent_id,
25 const string& name) {
26 std::unique_ptr<EntryKernel> kernel(new EntryKernel);
27 kernel_ = nullptr;
28
29 kernel->put(ID, trans->directory_->NextId());
30 kernel->put(META_HANDLE, trans->directory_->NextMetahandle());
31 kernel->mark_dirty(&trans->directory_->kernel()->dirty_metahandles);
32 kernel->put(NON_UNIQUE_NAME, name);
33 const base::Time& now = base::Time::Now();
34 kernel->put(CTIME, now);
35 kernel->put(MTIME, now);
36 // We match the database defaults here
37 kernel->put(BASE_VERSION, CHANGES_VERSION);
38
39 if (!parent_id.IsNull()) {
40 kernel->put(PARENT_ID, parent_id);
41 }
42
43 // Normally the SPECIFICS setting code is wrapped in logic to deal with
44 // unknown fields and encryption. Since all we want to do here is ensure that
45 // GetModelType() returns a correct value from the very beginning, these
46 // few lines are sufficient.
47 sync_pb::EntitySpecifics specifics;
48 AddDefaultFieldValue(model_type, &specifics);
49 kernel->put(SPECIFICS, specifics);
50
51 // Because this entry is new, it was originally deleted.
52 kernel->put(IS_DEL, true);
53 trans->TrackChangesTo(kernel.get());
54 kernel->put(IS_DEL, false);
55
56 // Now swap the pointers.
57 kernel_ = kernel.release();
58 }
59
60 MutableEntry::MutableEntry(WriteTransaction* trans, 22 MutableEntry::MutableEntry(WriteTransaction* trans,
61 Create, 23 Create,
62 ModelType model_type, 24 ModelType model_type,
63 const string& name) 25 const string& name)
64 : ModelNeutralMutableEntry(trans), write_transaction_(trans) { 26 : ModelNeutralMutableEntry(trans), write_transaction_(trans) {
65 Init(trans, model_type, Id(), name); 27 std::unique_ptr<EntryKernel> kernel =
28 CreateEntryKernel(trans, model_type, Id(), name);
29 kernel_ = kernel.get();
66 // We need to have a valid position ready before we can index the item. 30 // We need to have a valid position ready before we can index the item.
67 DCHECK_NE(BOOKMARKS, model_type); 31 DCHECK_NE(BOOKMARKS, model_type);
68 DCHECK(!ShouldMaintainPosition()); 32 DCHECK(!ShouldMaintainPosition());
69 33
70 bool result = trans->directory()->InsertEntry(trans, kernel_); 34 bool result = trans->directory()->InsertEntry(trans, std::move(kernel));
71 DCHECK(result); 35 DCHECK(result);
72 } 36 }
73 37
74 MutableEntry::MutableEntry(WriteTransaction* trans, 38 MutableEntry::MutableEntry(WriteTransaction* trans,
75 Create, 39 Create,
76 ModelType model_type, 40 ModelType model_type,
77 const Id& parent_id, 41 const Id& parent_id,
78 const string& name) 42 const string& name)
79 : ModelNeutralMutableEntry(trans), write_transaction_(trans) { 43 : ModelNeutralMutableEntry(trans), write_transaction_(trans) {
80 Init(trans, model_type, parent_id, name); 44 std::unique_ptr<EntryKernel> kernel =
45 CreateEntryKernel(trans, model_type, parent_id, name);
46 kernel_ = kernel.get();
81 // We need to have a valid position ready before we can index the item. 47 // We need to have a valid position ready before we can index the item.
82 if (model_type == BOOKMARKS) { 48 if (model_type == BOOKMARKS) {
83 // Base the tag off of our cache-guid and local "c-" style ID. 49 // Base the tag off of our cache-guid and local "c-" style ID.
84 std::string unique_tag = GenerateSyncableBookmarkHash( 50 std::string unique_tag = GenerateSyncableBookmarkHash(
85 trans->directory()->cache_guid(), GetId().GetServerId()); 51 trans->directory()->cache_guid(), GetId().GetServerId());
86 kernel_->put(UNIQUE_BOOKMARK_TAG, unique_tag); 52 kernel_->put(UNIQUE_BOOKMARK_TAG, unique_tag);
87 kernel_->put(UNIQUE_POSITION, UniquePosition::InitialPosition(unique_tag)); 53 kernel_->put(UNIQUE_POSITION, UniquePosition::InitialPosition(unique_tag));
88 } else { 54 } else {
89 DCHECK(!ShouldMaintainPosition()); 55 DCHECK(!ShouldMaintainPosition());
90 } 56 }
91 57
92 bool result = trans->directory()->InsertEntry(trans, kernel_); 58 bool result = trans->directory()->InsertEntry(trans, std::move(kernel));
93 DCHECK(result); 59 DCHECK(result);
94 } 60 }
95 61
96 MutableEntry::MutableEntry(WriteTransaction* trans, 62 MutableEntry::MutableEntry(WriteTransaction* trans,
97 CreateNewUpdateItem, 63 CreateNewUpdateItem,
98 const Id& id) 64 const Id& id)
99 : ModelNeutralMutableEntry(trans, CREATE_NEW_UPDATE_ITEM, id), 65 : ModelNeutralMutableEntry(trans, CREATE_NEW_UPDATE_ITEM, id),
100 write_transaction_(trans) {} 66 write_transaction_(trans) {}
101 67
102 MutableEntry::MutableEntry(WriteTransaction* trans, GetById, const Id& id) 68 MutableEntry::MutableEntry(WriteTransaction* trans, GetById, const Id& id)
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 attachment_metadata.mutable_record(i); 262 attachment_metadata.mutable_record(i);
297 if (record->id().unique_id() != attachment_id.unique_id()) 263 if (record->id().unique_id() != attachment_id.unique_id())
298 continue; 264 continue;
299 record->set_is_on_server(true); 265 record->set_is_on_server(true);
300 } 266 }
301 kernel_->put(ATTACHMENT_METADATA, attachment_metadata); 267 kernel_->put(ATTACHMENT_METADATA, attachment_metadata);
302 MarkDirty(); 268 MarkDirty();
303 MarkForSyncing(this); 269 MarkForSyncing(this);
304 } 270 }
305 271
272 // static
273 std::unique_ptr<EntryKernel> MutableEntry::CreateEntryKernel(
274 WriteTransaction* trans,
275 ModelType model_type,
276 const Id& parent_id,
277 const string& name) {
278 std::unique_ptr<EntryKernel> kernel(new EntryKernel);
279
280 kernel->put(ID, trans->directory_->NextId());
281 kernel->put(META_HANDLE, trans->directory_->NextMetahandle());
282 kernel->mark_dirty(&trans->directory_->kernel()->dirty_metahandles);
283 kernel->put(NON_UNIQUE_NAME, name);
284 const base::Time& now = base::Time::Now();
285 kernel->put(CTIME, now);
286 kernel->put(MTIME, now);
287 // We match the database defaults here
288 kernel->put(BASE_VERSION, CHANGES_VERSION);
289
290 if (!parent_id.IsNull()) {
291 kernel->put(PARENT_ID, parent_id);
292 }
293
294 // Normally the SPECIFICS setting code is wrapped in logic to deal with
295 // unknown fields and encryption. Since all we want to do here is ensure that
296 // GetModelType() returns a correct value from the very beginning, these
297 // few lines are sufficient.
298 sync_pb::EntitySpecifics specifics;
299 AddDefaultFieldValue(model_type, &specifics);
300 kernel->put(SPECIFICS, specifics);
301
302 // Because this entry is new, it was originally deleted.
303 kernel->put(IS_DEL, true);
304 trans->TrackChangesTo(kernel.get());
305 kernel->put(IS_DEL, false);
306 return kernel;
307 }
308
306 // This function sets only the flags needed to get this entry to sync. 309 // This function sets only the flags needed to get this entry to sync.
307 bool MarkForSyncing(MutableEntry* e) { 310 bool MarkForSyncing(MutableEntry* e) {
308 DCHECK_NE(static_cast<MutableEntry*>(nullptr), e); 311 DCHECK_NE(static_cast<MutableEntry*>(nullptr), e);
309 DCHECK(!e->IsRoot()) << "We shouldn't mark a permanent object for syncing."; 312 DCHECK(!e->IsRoot()) << "We shouldn't mark a permanent object for syncing.";
310 if (!(e->PutIsUnsynced(true))) 313 if (!(e->PutIsUnsynced(true)))
311 return false; 314 return false;
312 if (e->GetSyncing()) 315 if (e->GetSyncing())
313 e->PutDirtySync(true); 316 e->PutDirtySync(true);
314 return true; 317 return true;
315 } 318 }
316 319
317 } // namespace syncable 320 } // namespace syncable
318 } // namespace syncer 321 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/syncable/mutable_entry.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698