From 2835238287bab2304fbf1d7cc17b3a78686b4e51 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sat, 17 Aug 2013 14:05:36 -0500 Subject: [PATCH] Correct child and orphan block removal logic. It is not safe to remove elements from a slice while iterating them with the range statement since it does not reevaluate the slice on each iteration nor does it adjust the index for the modified slice. This commit modifies the code to use a for loop with an index (which does reevaluate on every iteration) and manually adjusts the index when elements are removed from the slice. --- chain.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/chain.go b/chain.go index d68463bdb..c02a91994 100644 --- a/chain.go +++ b/chain.go @@ -122,11 +122,16 @@ func removeChildNode(children []*blockNode, node *blockNode) []*blockNode { if node == nil { return children } - for i, n := range children { - if n.hash.IsEqual(node.hash) { + + // An indexing for loop is intentionally used over a range here as range + // does not reevaluate the slice on each iteration nor does it adjust + // the index for the modified slice. + for i := 0; i < len(children); i++ { + if children[i].hash.IsEqual(node.hash) { copy(children[i:], children[i+1:]) children[len(children)-1] = nil return children[:len(children)-1] + i-- } } return children @@ -186,15 +191,19 @@ func (b *BlockChain) removeOrphanBlock(orphan *orphanBlock) { orphanHash, _ := orphan.block.Sha() delete(b.orphans, *orphanHash) - // Remove the reference from the previous orphan index too. + // Remove the reference from the previous orphan index too. An indexing + // for loop is intentionally used over a range here as range does not + // reevaluate the slice on each iteration nor does it adjust the index + // for the modified slice. prevHash := &orphan.block.MsgBlock().Header.PrevBlock orphans := b.prevOrphans[*prevHash] - for i, ob := range orphans { - hash, _ := ob.block.Sha() + for i := 0; i < len(orphans); i++ { + hash, _ := orphans[i].block.Sha() if hash.IsEqual(orphanHash) { copy(orphans[i:], orphans[i+1:]) orphans[len(orphans)-1] = nil orphans = orphans[:len(orphans)-1] + i-- } } b.prevOrphans[*prevHash] = orphans