addrmgr: Fix AddressCache to not include nils

allAddr was being allocated with counters instead of the actual size
of the address map.  This led to the possibility of including nils
in the returned slice, which resulted in a panic.
This commit is contained in:
David Hill 2016-09-26 13:16:40 -04:00 committed by Dave Collins
parent 754c4fbe0c
commit 42a4366ba8

View file

@ -640,19 +640,19 @@ func (a *AddrManager) NeedMoreAddresses() bool {
func (a *AddrManager) AddressCache() []*wire.NetAddress { func (a *AddrManager) AddressCache() []*wire.NetAddress {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
if a.nNew+a.nTried == 0 {
addrIndexLen := len(a.addrIndex)
if addrIndexLen == 0 {
return nil return nil
} }
allAddr := make([]*wire.NetAddress, a.nNew+a.nTried) allAddr := make([]*wire.NetAddress, 0, addrIndexLen)
i := 0
// Iteration order is undefined here, but we randomise it anyway. // Iteration order is undefined here, but we randomise it anyway.
for _, v := range a.addrIndex { for _, v := range a.addrIndex {
allAddr[i] = v.na allAddr = append(allAddr, v.na)
i++
} }
numAddresses := len(allAddr) * getAddrPercent / 100 numAddresses := addrIndexLen * getAddrPercent / 100
if numAddresses > getAddrMax { if numAddresses > getAddrMax {
numAddresses = getAddrMax numAddresses = getAddrMax
} }
@ -661,12 +661,12 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress {
// `numAddresses' since we are throwing the rest. // `numAddresses' since we are throwing the rest.
for i := 0; i < numAddresses; i++ { for i := 0; i < numAddresses; i++ {
// pick a number between current index and the end // pick a number between current index and the end
j := rand.Intn(len(allAddr)-i) + i j := rand.Intn(addrIndexLen-i) + i
allAddr[i], allAddr[j] = allAddr[j], allAddr[i] allAddr[i], allAddr[j] = allAddr[j], allAddr[i]
} }
// slice off the limit we are willing to share. // slice off the limit we are willing to share.
return allAddr[:numAddresses] return allAddr[0:numAddresses]
} }
// reset resets the address manager by reinitialising the random source // reset resets the address manager by reinitialising the random source