Skip to content

Commit e8ec63a

Browse files
thepastaclawclaude
andcommitted
test: add regression tests for CoinJoin UB fixes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 817234f commit e8ec63a

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/test/coinjoin_queue_tests.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@
77
#include <active/masternode.h>
88
#include <bls/bls.h>
99
#include <coinjoin/coinjoin.h>
10+
#include <coinjoin/common.h>
11+
#include <consensus/amount.h>
1012

1113
#include <uint256.h>
1214

15+
#include <climits>
16+
#include <cstdint>
17+
1318
#include <boost/test/unit_test.hpp>
1419

1520
BOOST_FIXTURE_TEST_SUITE(coinjoin_queue_tests, TestingSetup)
@@ -96,4 +101,48 @@ BOOST_AUTO_TEST_CASE(queue_timestamp_validation)
96101
BOOST_CHECK(q.IsTimeOutOfBounds(current_time));
97102
}
98103

104+
BOOST_AUTO_TEST_CASE(queue_timestamp_extreme_values)
105+
{
106+
CCoinJoinQueue q;
107+
q.nDenom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination());
108+
q.m_protxHash = uint256::ONE;
109+
110+
// Negative timestamps are rejected by the guard
111+
q.nTime = INT64_MIN;
112+
BOOST_CHECK(q.IsTimeOutOfBounds(INT64_MAX));
113+
114+
q.nTime = INT64_MAX;
115+
BOOST_CHECK(q.IsTimeOutOfBounds(INT64_MIN));
116+
117+
q.nTime = INT64_MIN;
118+
BOOST_CHECK(q.IsTimeOutOfBounds(INT64_MIN));
119+
120+
// Large positive timestamp with same value: zero diff, in bounds
121+
q.nTime = INT64_MAX;
122+
BOOST_CHECK(!q.IsTimeOutOfBounds(INT64_MAX));
123+
124+
// Zero vs extreme positive: huge gap, out of bounds
125+
q.nTime = 0;
126+
BOOST_CHECK(q.IsTimeOutOfBounds(INT64_MAX));
127+
128+
// Zero vs negative: rejected by guard
129+
q.nTime = 0;
130+
BOOST_CHECK(q.IsTimeOutOfBounds(INT64_MIN));
131+
}
132+
133+
static_assert(CoinJoin::CalculateAmountPriority(MAX_MONEY) == -(MAX_MONEY / COIN));
134+
static_assert(CoinJoin::CalculateAmountPriority(static_cast<CAmount>(INT64_MAX)) == 0);
135+
static_assert(CoinJoin::CalculateAmountPriority(static_cast<CAmount>(-1)) == 0);
136+
137+
BOOST_AUTO_TEST_CASE(calculate_amount_priority_guard)
138+
{
139+
// Realistic amount: MAX_MONEY (21 million DASH)
140+
BOOST_CHECK_EQUAL(CoinJoin::CalculateAmountPriority(MAX_MONEY), -(MAX_MONEY / COIN));
141+
142+
// Out-of-range amounts return 0
143+
BOOST_CHECK_EQUAL(CoinJoin::CalculateAmountPriority(static_cast<CAmount>(INT64_MAX)), 0);
144+
BOOST_CHECK_EQUAL(CoinJoin::CalculateAmountPriority(static_cast<CAmount>(-1)), 0);
145+
BOOST_CHECK_EQUAL(CoinJoin::CalculateAmountPriority(MAX_MONEY + 1), 0);
146+
}
147+
99148
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)