From fa13bd6c97211f462506dd511856ee80ac9833cf Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 23 Nov 2024 20:12:56 +0100 Subject: [PATCH] core/state: fixes for issues found during fuzzing --- core/state/journal_linear.go | 19 +++++++++++++++++-- core/state/journal_set.go | 7 ++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/core/state/journal_linear.go b/core/state/journal_linear.go index e4b5571ef64e8..5bab167119675 100644 --- a/core/state/journal_linear.go +++ b/core/state/journal_linear.go @@ -53,9 +53,11 @@ var _ journal = (*linearJournal)(nil) // newLinearJournal creates a new initialized linearJournal. func newLinearJournal() *linearJournal { - return &linearJournal{ + s := &linearJournal{ dirties: make(map[common.Address]int), } + s.snapshot() // create snaphot zero + return s } // reset clears the journal, after this operation the journal can be used anew. @@ -65,6 +67,7 @@ func (j *linearJournal) reset() { j.entries = j.entries[:0] j.revisions = j.revisions[:0] clear(j.dirties) + j.snapshot() } func (j linearJournal) dirtyAccounts() []common.Address { @@ -84,10 +87,17 @@ func (j *linearJournal) snapshot() { // revertSnapshot reverts all state changes made since the last call to snapshot(). func (j *linearJournal) revertSnapshot(s *StateDB) { id := len(j.revisions) - 1 + if id < 0 { + j.snapshot() + return + } revision := j.revisions[id] // Replay the linearJournal to undo changes and remove invalidated snapshots j.revertTo(s, revision) j.revisions = j.revisions[:id] + if id == 0 { + j.snapshot() + } } // discardSnapshot removes the latest snapshot; after calling this @@ -95,7 +105,7 @@ func (j *linearJournal) revertSnapshot(s *StateDB) { // changes are considered part of the parent scope. func (j *linearJournal) discardSnapshot() { id := len(j.revisions) - 1 - if id == 0 { + if id <= 0 { // If a transaction is applied successfully, the statedb.Finalize will // end by clearing and resetting the journal. Invoking a discardSnapshot // afterwards will land here: calling discard on an empty journal. @@ -312,6 +322,11 @@ func (ch createContractChange) revert(s *StateDB) { } func (ch createContractChange) dirtied() *common.Address { + // This method returns nil, since the transformation from non-contract to + // contract is not an operation which has an effect on the trie: + // it does not make the account part of the dirty-set. + // Creating the account (createObject) or setting the code (setCode) + // however, do, and are. return nil } diff --git a/core/state/journal_set.go b/core/state/journal_set.go index d3dd57ea64e9a..1fa5e60006123 100644 --- a/core/state/journal_set.go +++ b/core/state/journal_set.go @@ -334,12 +334,14 @@ func newSparseJournal() *sparseJournal { // slices can be reused func (j *sparseJournal) reset() { j.entries = j.entries[:0] + j.ripeMagic = false j.snapshot() } func (j *sparseJournal) copy() journal { cp := &sparseJournal{ - entries: make([]*scopedJournal, 0, len(j.entries)), + entries: make([]*scopedJournal, 0, len(j.entries)), + ripeMagic: j.ripeMagic, } for _, entry := range j.entries { cp.entries = append(cp.entries, entry.deepCopy()) @@ -360,6 +362,9 @@ func (j *sparseJournal) revertSnapshot(s *StateDB) { id := len(j.entries) - 1 j.entries[id].revert(s) j.entries = j.entries[:id] + if id == 0 { + j.snapshot() + } } // discardSnapshot removes the latest snapshot; after calling this