Skip to content

Commit 5292ddb

Browse files
committed
trie, eth/protocols/snap: sanitize the committed node data
1 parent 7ed52c9 commit 5292ddb

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

eth/protocols/snap/sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2358,7 +2358,7 @@ func (s *Syncer) commitHealer(force bool) {
23582358
}
23592359
batch := s.db.NewBatch()
23602360
if err := s.healer.scheduler.Commit(batch); err != nil {
2361-
log.Error("Failed to commit healing data", "err", err)
2361+
log.Crit("Failed to commit healing data", "err", err)
23622362
}
23632363
if err := batch.Write(); err != nil {
23642364
log.Crit("Failed to persist healing data", "err", err)

trie/sync.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"sync"
2323

2424
"github.com/ethereum/go-ethereum/common"
25+
"github.com/ethereum/go-ethereum/common/hexutil"
2526
"github.com/ethereum/go-ethereum/common/prque"
2627
"github.com/ethereum/go-ethereum/core/rawdb"
2728
"github.com/ethereum/go-ethereum/core/types"
@@ -149,15 +150,42 @@ type CodeSyncResult struct {
149150
// nodeOp represents an operation upon the trie node. It can either represent a
150151
// deletion to the specific node or a node write for persisting retrieved node.
151152
type nodeOp struct {
153+
del bool // flag if op stands for a delete operation
152154
owner common.Hash // identifier of the trie (empty for account trie)
153155
path []byte // path from the root to the specified node.
154156
blob []byte // the content of the node (nil for deletion)
155157
hash common.Hash // hash of the node content (empty for node deletion)
156158
}
157159

158160
// isDelete indicates if the operation is a database deletion.
159-
func (op *nodeOp) isDelete() bool {
160-
return len(op.blob) == 0
161+
func (op *nodeOp) valid() bool {
162+
if op.del && len(op.blob) != 0 {
163+
return false
164+
}
165+
if !op.del && len(op.blob) == 0 {
166+
return false
167+
}
168+
return true
169+
}
170+
171+
// string returns the node operation in string representation.
172+
func (op *nodeOp) string() string {
173+
var node string
174+
if op.owner == (common.Hash{}) {
175+
node = fmt.Sprintf("node: (%v)", op.path)
176+
} else {
177+
node = fmt.Sprintf("node: (%x-%v)", op.owner, op.path)
178+
}
179+
var blobHex string
180+
if len(op.blob) == 0 {
181+
blobHex = "nil"
182+
} else {
183+
blobHex = hexutil.Encode(op.blob)
184+
}
185+
if op.del {
186+
return fmt.Sprintf("del %s %s %s", node, blobHex, op.hash.Hex())
187+
}
188+
return fmt.Sprintf("write %s %s %s", node, blobHex, op.hash.Hex())
161189
}
162190

163191
// syncMemBatch is an in-memory buffer of successfully downloaded but not yet
@@ -220,6 +248,7 @@ func (batch *syncMemBatch) delNode(owner common.Hash, path []byte) {
220248
batch.size += common.HashLength + uint64(len(path))
221249
}
222250
batch.nodes = append(batch.nodes, nodeOp{
251+
del: true,
223252
owner: owner,
224253
path: path,
225254
})
@@ -428,7 +457,10 @@ func (s *Sync) Commit(dbw ethdb.Batch) error {
428457
storage int
429458
)
430459
for _, op := range s.membatch.nodes {
431-
if op.isDelete() {
460+
if !op.valid() {
461+
return fmt.Errorf("invalid op, %s", op.string())
462+
}
463+
if op.del {
432464
// node deletion is only supported in path mode.
433465
if op.owner == (common.Hash{}) {
434466
rawdb.DeleteAccountTrieNode(dbw, op.path)

0 commit comments

Comments
 (0)