Fix likely unintentional unsigned integer wrap-around in GetBlockProofEquivalentTime(...)
when to.nChainWork <= from.nChainWork
.
Description:
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, …)
contains the following code:
0int sign = 1;
1if (to.nChainWork > from.nChainWork) {
2…
3} else {
4 …
5 sign = -1;
6}
7…
8return sign * r.GetLow64();
r.GetLow64()
is of type uint64_t
.
Note that the types of the two operands in sign * r.GetLow64()
differ in signedness.
Since uint64_t
is wider than int
the signed operand (sign
) is converted to the unsigned type.
In the case of sign == -1
(to.nChainWork <= from.nChainWork
) we wrap around and end up with 18446744073709551615 * r.GetLow64()
(std::numeric_limits<uint64_t>::max() * r.GetLow64()
) instead of the intended -1 * r.GetLow64()
.
Note however that another conversion takes place when the result is converted into the return type
(int64_t
), so the resulting value should be the expected one (equivalent to -1 * r.GetLow64()
).
In the case that this behaviour (wrap-around + relying on return type to fix) is intentional a comment should probably be added to indicate so :-)
GetBlockProofEquivalentTime(…)
was introduced in f7303f97933be33e34d482cf8348d180c8da2a26. Friendly ping @sipa - intentional or not? :-)