From 219a6131f4169c9b5ca9dc9420278ffa1a5f6d32 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 7 Oct 2013 09:04:11 -0500 Subject: [PATCH] Correct all list/container loops that remove items. It is not safe to remove an item from a container/list while iterating the list without first saving the next pointer since removing the item nils the internal list element's next pointer. --- blockmanager.go | 8 ++++++-- mempool.go | 4 +++- server.go | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 8f5f408a..8066de39 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -95,7 +95,9 @@ func (b *blockManager) startSync(peers *list.List) { } var bestPeer *peer - for e := peers.Front(); e != nil; e = e.Next() { + var enext *list.Element + for e := peers.Front(); e != nil; e = enext { + enext = e.Next() p := e.Value.(*peer) // Remove sync candidate peers that are no longer candidates due @@ -187,7 +189,9 @@ func (b *blockManager) handleNewPeerMsg(peers *list.List, p *peer) { // is invoked from the syncHandler goroutine. func (b *blockManager) handleDonePeerMsg(peers *list.List, p *peer) { // Remove the peer from the list of candidate peers. - for e := peers.Front(); e != nil; e = e.Next() { + var enext *list.Element + for e := peers.Front(); e != nil; e = enext { + enext = e.Next() if e.Value == p { peers.Remove(e) break diff --git a/mempool.go b/mempool.go index 4401225a..2909cc94 100644 --- a/mempool.go +++ b/mempool.go @@ -292,7 +292,9 @@ func (mp *txMemPool) removeOrphan(txHash *btcwire.ShaHash) { for _, txIn := range tx.TxIn { originTxHash := txIn.PreviousOutpoint.Hash if orphans, exists := mp.orphansByPrev[originTxHash]; exists { - for e := orphans.Front(); e != nil; e = e.Next() { + var enext *list.Element + for e := orphans.Front(); e != nil; e = enext { + enext = e.Next() if e.Value.(*btcwire.MsgTx) == tx { orphans.Remove(e) break diff --git a/server.go b/server.go index 90d6d395..6576b203 100644 --- a/server.go +++ b/server.go @@ -116,7 +116,9 @@ func (s *server) handleAddPeerMsg(peers *list.List, banned map[string]time.Time, // handleDonePeerMsg deals with peers that have signalled they are done. It is // invoked from the peerHandler goroutine. func (s *server) handleDonePeerMsg(peers *list.List, p *peer) bool { - for e := peers.Front(); e != nil; e = e.Next() { + var enext *list.Element + for e := peers.Front(); e != nil; e = enext { + enext = e.Next() if e.Value == p { // Issue an asynchronous reconnect if the peer was a // persistent outbound connection.