From 409add9f63cd88fa202f9be4de9b903baeff589e Mon Sep 17 00:00:00 2001 From: alienx5499 Date: Sat, 28 Feb 2026 16:18:49 +0530 Subject: [PATCH] Fix overflow for permanent peer address TTL --- .../inmem_address_repository.cpp | 8 ++++ .../inmem_address_repository_test.cpp | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/peer/address_repository/inmem_address_repository.cpp b/src/peer/address_repository/inmem_address_repository.cpp index 518083580..bdc3d6377 100644 --- a/src/peer/address_repository/inmem_address_repository.cpp +++ b/src/peer/address_repository/inmem_address_repository.cpp @@ -67,6 +67,14 @@ namespace libp2p::peer { Clock::time_point InmemAddressRepository::calculateExpirationTime( const Milliseconds &ttl) const { static const auto max_time = Clock::time_point::max(); + // permanent TTLs use milliseconds::max() as a sentinel + // doing arithmetic with that value (e.g. now + ttl or max_time - ttl) + // can overflow chrono durations and cause undefined behaviour + // instead of touching the sentinel in time math, map it directly to + // time_point::max() to mean "never expires" + if (ttl == ttl::kPermanent) { + return max_time; + } const auto now = Clock::now(); if (now >= max_time - ttl) { return max_time; diff --git a/test/libp2p/peer/address_repository/inmem_address_repository_test.cpp b/test/libp2p/peer/address_repository/inmem_address_repository_test.cpp index 0faa9cc75..64340d4d9 100644 --- a/test/libp2p/peer/address_repository/inmem_address_repository_test.cpp +++ b/test/libp2p/peer/address_repository/inmem_address_repository_test.cpp @@ -186,3 +186,41 @@ TEST_F(InmemAddressRepository_Test, GetPeers) { auto s = db->getPeers(); EXPECT_EQ(s.size(), 2); } + +/** + * @given address repository + * @when addAddresses/upsertAddresses with ttl::kPermanent + * @then addresses are stored and not evicted by collectGarbage + */ +TEST_F(InmemAddressRepository_Test, PermanentTtlNoOverflow) { + ASSERT_OUTCOME_SUCCESS( + db->addAddresses(p1, std::vector{ma1, ma2}, ttl::kPermanent)); + ASSERT_OUTCOME_SUCCESS( + db->upsertAddresses(p2, std::vector{ma3}, ttl::kPermanent)); + + ASSERT_OUTCOME_SUCCESS(v1, db->getAddresses(p1)); + ASSERT_OUTCOME_SUCCESS(v2, db->getAddresses(p2)); + EXPECT_EQ(v1.size(), 2); + EXPECT_EQ(v2.size(), 1); + + collectGarbage(); + ASSERT_OUTCOME_SUCCESS(a1, db->getAddresses(p1)); + ASSERT_OUTCOME_SUCCESS(a2, db->getAddresses(p2)); + EXPECT_EQ(a1.size(), 2); + EXPECT_EQ(a2.size(), 1); + EXPECT_FALSE(a1.empty()); + EXPECT_FALSE(a2.empty()); +} + +TEST_F(InmemAddressRepository_Test, LargeTtlClampedToMax) { + using namespace std::chrono; + auto large_ttl = milliseconds::max() - milliseconds(1); + + ASSERT_OUTCOME_SUCCESS( + db->addAddresses(p1, std::vector{ma1}, large_ttl)); + + collectGarbage(); + + ASSERT_OUTCOME_SUCCESS(v, db->getAddresses(p1)); + EXPECT_EQ(v.size(), 1); +}