diff --git a/src/random.cpp b/src/random.cpp index 092e04701..97e64bc8e 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -47,6 +47,7 @@ uint128_t GetRandUInt128(uint128_t nMax) int128_t GetRandInt128(int128_t nMax) { + assert(nMax >= 0); return GetRandUInt128(nMax); } @@ -57,11 +58,13 @@ uint64_t GetRand(uint64_t nMax) int64_t GetRandInt64(int64_t nMax) { + assert(nMax >= 0); return GetRand(nMax); } int GetRandInt(int nMax) { + assert(nMax >= 0); return GetRand(nMax); } diff --git a/src/random.h b/src/random.h index 6a091ea3f..859c10715 100644 --- a/src/random.h +++ b/src/random.h @@ -24,7 +24,9 @@ void GetRandBytes(unsigned char* buf, size_t num); template I GetRandGeneric(I nMax) { + // I must be an unsigned numeric type. static_assert(std::numeric_limits::min() == 0); + // I() for primitive signed integer types returns 0. if (nMax == I()) return I(); diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index ae96d4f2e..0808fe406 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -31,6 +31,7 @@ public: int RandomInt(int nMax) { + assert(nMax >= 0); state = (CHashWriter(SER_GETHASH, 0) << state).GetHash().GetCheapHash(); return (unsigned int)(state % nMax); } diff --git a/src/weighted_map.h b/src/weighted_map.h index 7511b9959..b641ec57d 100644 --- a/src/weighted_map.h +++ b/src/weighted_map.h @@ -22,13 +22,17 @@ // weights of the children. This allows for addition, removal, and random // selection/dropping in logarithmic time. // -// random(w) must be defined to return a uniform random value between zero -// inclusive and w exclusive. The type W must support addition, binary and -// unary -, and < comparisons, and W() must construct the zero value (these -// constraints are met for primitive signed integer types). +// random(w) (which will only be called with positive w) must be defined to +// return a uniform random value between zero inclusive and w exclusive. +// The type W must be a signed numeric type that supports addition, binary +// and unary -, and < and <= comparisons, and W() must construct the zero value +// (these constraints are met for primitive signed integer types). template class WeightedMap { + // W must be a signed numeric type. + static_assert(std::numeric_limits::min() < W()); + struct Node { K key; V value; @@ -180,6 +184,7 @@ public: return std::nullopt; } W totalWeight = getTotalWeight(); + assert(W() < totalWeight); W randomWeight = random(totalWeight); assert(W() <= randomWeight && randomWeight < totalWeight); size_t index = findByWeight(0, randomWeight);