Skip to content

Commit 409add9

Browse files
committed
Fix overflow for permanent peer address TTL
1 parent 347eb8d commit 409add9

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

src/peer/address_repository/inmem_address_repository.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ namespace libp2p::peer {
6767
Clock::time_point InmemAddressRepository::calculateExpirationTime(
6868
const Milliseconds &ttl) const {
6969
static const auto max_time = Clock::time_point::max();
70+
// permanent TTLs use milliseconds::max() as a sentinel
71+
// doing arithmetic with that value (e.g. now + ttl or max_time - ttl)
72+
// can overflow chrono durations and cause undefined behaviour
73+
// instead of touching the sentinel in time math, map it directly to
74+
// time_point::max() to mean "never expires"
75+
if (ttl == ttl::kPermanent) {
76+
return max_time;
77+
}
7078
const auto now = Clock::now();
7179
if (now >= max_time - ttl) {
7280
return max_time;

test/libp2p/peer/address_repository/inmem_address_repository_test.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,41 @@ TEST_F(InmemAddressRepository_Test, GetPeers) {
186186
auto s = db->getPeers();
187187
EXPECT_EQ(s.size(), 2);
188188
}
189+
190+
/**
191+
* @given address repository
192+
* @when addAddresses/upsertAddresses with ttl::kPermanent
193+
* @then addresses are stored and not evicted by collectGarbage
194+
*/
195+
TEST_F(InmemAddressRepository_Test, PermanentTtlNoOverflow) {
196+
ASSERT_OUTCOME_SUCCESS(
197+
db->addAddresses(p1, std::vector<Multiaddress>{ma1, ma2}, ttl::kPermanent));
198+
ASSERT_OUTCOME_SUCCESS(
199+
db->upsertAddresses(p2, std::vector<Multiaddress>{ma3}, ttl::kPermanent));
200+
201+
ASSERT_OUTCOME_SUCCESS(v1, db->getAddresses(p1));
202+
ASSERT_OUTCOME_SUCCESS(v2, db->getAddresses(p2));
203+
EXPECT_EQ(v1.size(), 2);
204+
EXPECT_EQ(v2.size(), 1);
205+
206+
collectGarbage();
207+
ASSERT_OUTCOME_SUCCESS(a1, db->getAddresses(p1));
208+
ASSERT_OUTCOME_SUCCESS(a2, db->getAddresses(p2));
209+
EXPECT_EQ(a1.size(), 2);
210+
EXPECT_EQ(a2.size(), 1);
211+
EXPECT_FALSE(a1.empty());
212+
EXPECT_FALSE(a2.empty());
213+
}
214+
215+
TEST_F(InmemAddressRepository_Test, LargeTtlClampedToMax) {
216+
using namespace std::chrono;
217+
auto large_ttl = milliseconds::max() - milliseconds(1);
218+
219+
ASSERT_OUTCOME_SUCCESS(
220+
db->addAddresses(p1, std::vector<Multiaddress>{ma1}, large_ttl));
221+
222+
collectGarbage();
223+
224+
ASSERT_OUTCOME_SUCCESS(v, db->getAddresses(p1));
225+
EXPECT_EQ(v.size(), 1);
226+
}

0 commit comments

Comments
 (0)