Skip to content

Commit b9ff613

Browse files
committed
Fix potential UB in CalculateFACTORASERT
1 parent 5f221c1 commit b9ff613

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/pow.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,19 @@ ASERTResult CalculateFACTORASERT(const FACTORASERTParams& params,
148148
// Direct (time_error << 32) overflows int64_t at |time_error| > ~2.15e9.
149149
// This variant overflows only at |time_error| > 2^31 * halfLife (~11.7M years
150150
// on mainnet), effectively eliminating the concern.
151+
//
152+
// Shifts go through uint64_t: in C++17, left-shifting a negative signed
153+
// value is undefined behavior ([expr.shift]/2), which would fire for every
154+
// slow-block header. The unsigned round-trip produces the same bit pattern
155+
// on two's-complement platforms and is well-defined.
151156
const int64_t integer_part = time_error / params.halfLife;
152157
const int64_t remainder = time_error % params.halfLife;
153-
const int64_t exponent_q32 = (integer_part << 32)
154-
+ ((remainder << 32) / params.halfLife);
158+
const int64_t integer_shifted =
159+
static_cast<int64_t>(static_cast<uint64_t>(integer_part) << 32);
160+
const int64_t remainder_shifted =
161+
static_cast<int64_t>(static_cast<uint64_t>(remainder) << 32);
162+
const int64_t exponent_q32 = integer_shifted
163+
+ (remainder_shifted / params.halfLife);
155164

156165
// --- Step 3: Compute target log2_compute ---
157166
const int64_t target_log2_compute = anchor_log2_compute + exponent_q32;

0 commit comments

Comments
 (0)