Skip to content

Commit 7ed597f

Browse files
authored
Merge pull request #1453 from tomt1664/addrman_fix_cherrypick
Cherry-pick bitcoin#30568: addrman: change internal id counting to int64_t
2 parents 38357ed + 285f81b commit 7ed597f

File tree

3 files changed

+39
-32
lines changed

3 files changed

+39
-32
lines changed

src/addrman.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ void AddrManImpl::Serialize(Stream& s_) const
182182

183183
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
184184
s << nUBuckets;
185-
std::unordered_map<int, int> mapUnkIds;
185+
std::unordered_map<nid_type, int> mapUnkIds;
186186
int nIds = 0;
187187
for (const auto& entry : mapInfo) {
188188
mapUnkIds[entry.first] = nIds;
@@ -397,7 +397,7 @@ void AddrManImpl::Unserialize(Stream& s_)
397397
}
398398
}
399399

400-
AddrInfo* AddrManImpl::Find(const CService& addr, int* pnId)
400+
AddrInfo* AddrManImpl::Find(const CService& addr, nid_type* pnId)
401401
{
402402
AssertLockHeld(cs);
403403

@@ -412,11 +412,11 @@ AddrInfo* AddrManImpl::Find(const CService& addr, int* pnId)
412412
return nullptr;
413413
}
414414

415-
AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
415+
AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource, nid_type* pnId)
416416
{
417417
AssertLockHeld(cs);
418418

419-
int nId = nIdCount++;
419+
nid_type nId = nIdCount++;
420420
mapInfo[nId] = AddrInfo(addr, addrSource);
421421
mapAddr[addr] = nId;
422422
mapInfo[nId].nRandomPos = vRandom.size();
@@ -435,8 +435,8 @@ void AddrManImpl::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
435435

436436
assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
437437

438-
int nId1 = vRandom[nRndPos1];
439-
int nId2 = vRandom[nRndPos2];
438+
nid_type nId1 = vRandom[nRndPos1];
439+
nid_type nId2 = vRandom[nRndPos2];
440440

441441
const auto it_1{mapInfo.find(nId1)};
442442
const auto it_2{mapInfo.find(nId2)};
@@ -450,7 +450,7 @@ void AddrManImpl::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
450450
vRandom[nRndPos2] = nId1;
451451
}
452452

453-
void AddrManImpl::Delete(int nId)
453+
void AddrManImpl::Delete(nid_type nId)
454454
{
455455
AssertLockHeld(cs);
456456

@@ -472,7 +472,7 @@ void AddrManImpl::ClearNew(int nUBucket, int nUBucketPos)
472472

473473
// if there is an entry in the specified bucket, delete it.
474474
if (vvNew[nUBucket][nUBucketPos] != -1) {
475-
int nIdDelete = vvNew[nUBucket][nUBucketPos];
475+
nid_type nIdDelete = vvNew[nUBucket][nUBucketPos];
476476
AddrInfo& infoDelete = mapInfo[nIdDelete];
477477
assert(infoDelete.nRefCount > 0);
478478
infoDelete.nRefCount--;
@@ -484,7 +484,7 @@ void AddrManImpl::ClearNew(int nUBucket, int nUBucketPos)
484484
}
485485
}
486486

487-
void AddrManImpl::MakeTried(AddrInfo& info, int nId)
487+
void AddrManImpl::MakeTried(AddrInfo& info, nid_type nId)
488488
{
489489
AssertLockHeld(cs);
490490

@@ -510,7 +510,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
510510
// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
511511
if (vvTried[nKBucket][nKBucketPos] != -1) {
512512
// find an item to evict
513-
int nIdEvict = vvTried[nKBucket][nKBucketPos];
513+
nid_type nIdEvict = vvTried[nKBucket][nKBucketPos];
514514
assert(mapInfo.count(nIdEvict) == 1);
515515
AddrInfo& infoOld = mapInfo[nIdEvict];
516516

@@ -546,7 +546,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
546546
if (!addr.IsRoutable())
547547
return false;
548548

549-
int nId;
549+
nid_type nId;
550550
AddrInfo* pinfo = Find(addr, &nId);
551551

552552
// Do not set a penalty for a source's self-announcement
@@ -618,7 +618,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
618618
{
619619
AssertLockHeld(cs);
620620

621-
int nId;
621+
nid_type nId;
622622

623623
nLastGood = nTime;
624624

@@ -845,8 +845,8 @@ void AddrManImpl::ResolveCollisions_()
845845
{
846846
AssertLockHeld(cs);
847847

848-
for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
849-
int id_new = *it;
848+
for (std::set<nid_type>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
849+
nid_type id_new = *it;
850850

851851
bool erase_collision = false;
852852

@@ -864,7 +864,7 @@ void AddrManImpl::ResolveCollisions_()
864864
} else if (vvTried[tried_bucket][tried_bucket_pos] != -1) { // The position in the tried bucket is not empty
865865

866866
// Get the to-be-evicted address that is being tested
867-
int id_old = vvTried[tried_bucket][tried_bucket_pos];
867+
nid_type id_old = vvTried[tried_bucket][tried_bucket_pos];
868868
AddrInfo& info_old = mapInfo[id_old];
869869

870870
// Has successfully connected in last X hours
@@ -908,11 +908,11 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()
908908

909909
if (m_tried_collisions.size() == 0) return {};
910910

911-
std::set<int>::iterator it = m_tried_collisions.begin();
911+
std::set<nid_type>::iterator it = m_tried_collisions.begin();
912912

913913
// Selects a random element from m_tried_collisions
914914
std::advance(it, insecure_rand.randrange(m_tried_collisions.size()));
915-
int id_new = *it;
915+
nid_type id_new = *it;
916916

917917
// If id_new not found in mapInfo remove it from m_tried_collisions
918918
if (mapInfo.count(id_new) != 1) {
@@ -975,14 +975,14 @@ int AddrManImpl::CheckAddrman() const
975975
LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(
976976
strprintf("new %i, tried %i, total %u", nNew, nTried, vRandom.size()), BCLog::ADDRMAN);
977977

978-
std::unordered_set<int> setTried;
979-
std::unordered_map<int, int> mapNew;
978+
std::unordered_set<nid_type> setTried;
979+
std::unordered_map<nid_type, int> mapNew;
980980

981981
if (vRandom.size() != (size_t)(nTried + nNew))
982982
return -7;
983983

984984
for (const auto& entry : mapInfo) {
985-
int n = entry.first;
985+
nid_type n = entry.first;
986986
const AddrInfo& info = entry.second;
987987
if (info.fInTried) {
988988
if (!info.nLastSuccess)

src/addrman_impl.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ static constexpr int ADDRMAN_NEW_BUCKET_COUNT{1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2
3131
static constexpr int32_t ADDRMAN_BUCKET_SIZE_LOG2{6};
3232
static constexpr int ADDRMAN_BUCKET_SIZE{1 << ADDRMAN_BUCKET_SIZE_LOG2};
3333

34+
/**
35+
* User-defined type for the internally used nIds
36+
* This used to be int, making it feasible for attackers to cause an overflow,
37+
* see https://bitcoincore.org/en/2024/07/31/disclose-addrman-int-overflow/
38+
*/
39+
using nid_type = int64_t;
40+
3441
/**
3542
* Extended statistics about a CAddress
3643
*/
@@ -178,36 +185,36 @@ class AddrManImpl
178185
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
179186

180187
//! last used nId
181-
int nIdCount GUARDED_BY(cs){0};
188+
nid_type nIdCount GUARDED_BY(cs){0};
182189

183190
//! table with information about all nIds
184-
std::unordered_map<int, AddrInfo> mapInfo GUARDED_BY(cs);
191+
std::unordered_map<nid_type, AddrInfo> mapInfo GUARDED_BY(cs);
185192

186193
//! find an nId based on its network address and port.
187-
std::unordered_map<CService, int, CServiceHash> mapAddr GUARDED_BY(cs);
194+
std::unordered_map<CService, nid_type, CServiceHash> mapAddr GUARDED_BY(cs);
188195

189196
//! randomly-ordered vector of all nIds
190197
//! This is mutable because it is unobservable outside the class, so any
191198
//! changes to it (even in const methods) are also unobservable.
192-
mutable std::vector<int> vRandom GUARDED_BY(cs);
199+
mutable std::vector<nid_type> vRandom GUARDED_BY(cs);
193200

194201
// number of "tried" entries
195202
int nTried GUARDED_BY(cs){0};
196203

197204
//! list of "tried" buckets
198-
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
205+
nid_type vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
199206

200207
//! number of (unique) "new" entries
201208
int nNew GUARDED_BY(cs){0};
202209

203210
//! list of "new" buckets
204-
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
211+
nid_type vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
205212

206213
//! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
207214
int64_t nLastGood GUARDED_BY(cs){1};
208215

209216
//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
210-
std::set<int> m_tried_collisions;
217+
std::set<nid_type> m_tried_collisions;
211218

212219
/** Perform consistency checks every m_consistency_check_ratio operations (if non-zero). */
213220
const int32_t m_consistency_check_ratio;
@@ -229,22 +236,22 @@ class AddrManImpl
229236
const std::vector<bool> m_asmap;
230237

231238
//! Find an entry.
232-
AddrInfo* Find(const CService& addr, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
239+
AddrInfo* Find(const CService& addr, nid_type* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
233240

234241
//! Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
235-
AddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
242+
AddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, nid_type* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
236243

237244
//! Swap two elements in vRandom.
238245
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs);
239246

240247
//! Delete an entry. It must not be in tried, and have refcount 0.
241-
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
248+
void Delete(nid_type nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
242249

243250
//! Clear a position in a "new" table. This is the only place where entries are actually deleted.
244251
void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
245252

246253
//! Move an entry from the "new" table(s) to the "tried" table
247-
void MakeTried(AddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
254+
void MakeTried(AddrInfo& info, nid_type nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
248255

249256
/** Attempt to add a single address to addrman's new table.
250257
* @see AddrMan::Add() for parameters. */

src/test/fuzz/addrman.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ class AddrManDeterministic : public AddrMan
189189
return false;
190190
}
191191

192-
auto IdsReferToSameAddress = [&](int id, int other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
192+
auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
193193
if (id == -1 && other_id == -1) {
194194
return true;
195195
}

0 commit comments

Comments
 (0)