Skip to content

Commit b7d0cb1

Browse files
authored
Avoid undefined behavior in RANLUX++ (#8522)
Left shifting a negative base is undefined behavior until C++20, cast to unsigned where it becomes implementation defined already in earlier standards and works in practice because hardware uses two's complement. Fixes #8503
1 parent 2c0f22e commit b7d0cb1

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

math/mathcore/src/ranluxpp/mulmod.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,14 @@ static void mod_m(const uint64_t *mul, uint64_t *out)
165165
// (The assembly implementation shifts by 63, which gives the same result.)
166166
int64_t t0 = c >> 1;
167167

168+
// Left shifting negative values is undefined behavior until C++20, cast to
169+
// unsigned.
170+
uint64_t c_unsigned = static_cast<uint64_t>(c);
171+
168172
// c = 0 -> t2 = 0; c = 1 -> upper 16 bits set; c = -1 -> lower 48 bits set
169-
int64_t t2 = t0 - (c << 48);
173+
int64_t t2 = t0 - (c_unsigned << 48);
170174

171-
// c = 0 -> t1 = 0; c = 1 -> all bits set; c = -1 -> t1 = 0
175+
// c = 0 -> t1 = 0; c = 1 -> all bits set (sign extension); c = -1 -> t1 = 0
172176
// (The assembly implementation shifts by 63, which gives the same result.)
173177
int64_t t1 = t2 >> 48;
174178

0 commit comments

Comments
 (0)