Add checks for adjacent nodes in flush-list updates

Added checks to ensure adjacent nodes exist before updating the flush-list, preventing potential nil dereference errors.
This commit is contained in:
Avory 2026-01-03 15:51:38 +02:00 committed by GitHub
parent b635e0632c
commit fbbea339e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -165,7 +165,12 @@ func (db *Database) insert(hash common.Hash, node []byte) {
if db.oldest == (common.Hash{}) { if db.oldest == (common.Hash{}) {
db.oldest, db.newest = hash, hash db.oldest, db.newest = hash, hash
} else { } else {
db.dirties[db.newest].flushNext, db.newest = hash, hash if newestNode, ok := db.dirties[db.newest]; ok {
newestNode.flushNext, db.newest = hash, hash
} else {
// Flush-list is corrupted, reset it
db.oldest, db.newest = hash, hash
}
} }
db.dirtiesSize += common.StorageSize(common.HashLength + len(node)) db.dirtiesSize += common.StorageSize(common.HashLength + len(node))
} }
@ -238,10 +243,15 @@ func (db *Database) reference(child common.Hash, parent common.Hash) {
} }
// The reference is for external storage trie, don't duplicate if // The reference is for external storage trie, don't duplicate if
// the reference is already existent. // the reference is already existent.
if db.dirties[parent].external == nil { parentNode, ok := db.dirties[parent]
db.dirties[parent].external = make(map[common.Hash]struct{}) if !ok {
// Parent node doesn't exist in dirties, skip
return
} }
if _, ok := db.dirties[parent].external[child]; ok { if parentNode.external == nil {
parentNode.external = make(map[common.Hash]struct{})
}
if _, ok := parentNode.external[child]; ok {
return return
} }
node.parents++ node.parents++
@ -303,8 +313,13 @@ func (db *Database) dereference(hash common.Hash) {
db.dirties[node.flushPrev].flushNext = common.Hash{} db.dirties[node.flushPrev].flushNext = common.Hash{}
} }
default: default:
db.dirties[node.flushPrev].flushNext = node.flushNext // Verify that adjacent nodes exist before updating flush-list
db.dirties[node.flushNext].flushPrev = node.flushPrev if prevNode, ok := db.dirties[node.flushPrev]; ok {
prevNode.flushNext = node.flushNext
}
if nextNode, ok := db.dirties[node.flushNext]; ok {
nextNode.flushPrev = node.flushPrev
}
} }
// Dereference all children and delete the node // Dereference all children and delete the node
node.forChildren(func(child common.Hash) { node.forChildren(func(child common.Hash) {
@ -511,8 +526,13 @@ func (c *cleaner) Put(key []byte, rlp []byte) error {
c.db.dirties[node.flushPrev].flushNext = common.Hash{} c.db.dirties[node.flushPrev].flushNext = common.Hash{}
} }
default: default:
c.db.dirties[node.flushPrev].flushNext = node.flushNext // Verify that adjacent nodes exist before updating flush-list
c.db.dirties[node.flushNext].flushPrev = node.flushPrev if prevNode, ok := c.db.dirties[node.flushPrev]; ok {
prevNode.flushNext = node.flushNext
}
if nextNode, ok := c.db.dirties[node.flushNext]; ok {
nextNode.flushPrev = node.flushPrev
}
} }
// Remove the node from the dirty cache // Remove the node from the dirty cache
delete(c.db.dirties, hash) delete(c.db.dirties, hash)