[tz] [PROPOSED 1/6] Don’t assume INT_MAX < UINT_FAST64_MAX
Paul Eggert
eggert at cs.ucla.edu
Sun Nov 20 05:47:55 UTC 2022
* zic.c (get_rand_u64): Avoid undefined behavior in getrandom
fallback, on theoretical platforms where UINT_FAST64_MAX <= INT_MAX
so a * b can have signed integer overflow even though A and B are
uint_fast64_t.
---
zic.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/zic.c b/zic.c
index 45dffea..26595c2 100644
--- a/zic.c
+++ b/zic.c
@@ -1230,13 +1230,21 @@ get_rand_u64(void)
the typical case where RAND_MAX is one less than a power of two.
In other cases this code yields a sort-of-random number. */
{
- uint_fast64_t
- rand_max = RAND_MAX,
- multiplier = rand_max + 1, /* It's OK if this overflows to 0. */
+ uint_fast64_t rand_max = RAND_MAX,
+ nrand = rand_max < UINT_FAST64_MAX ? rand_max + 1 : 0,
+ rmod = INT_MAX < UINT_FAST64_MAX ? 0 : UINT_FAST64_MAX / nrand + 1,
r = 0, rmax = 0;
+
do {
- uint_fast64_t rmax1 = rmax * multiplier + rand_max;
- r = r * multiplier + rand();
+ uint_fast64_t rmax1 = rmax;
+ if (rmod) {
+ /* Avoid signed integer overflow on theoretical platforms
+ where uint_fast64_t promotes to int. */
+ rmax1 %= rmod;
+ r %= rmod;
+ }
+ rmax1 = nrand * rmax1 + rand_max;
+ r = nrand * r + rand();
rmax = rmax < rmax1 ? rmax1 : UINT_FAST64_MAX;
} while (rmax < UINT_FAST64_MAX);
--
2.38.1
More information about the tz
mailing list