Fix overflow in guf_rand32range_i32 and guf_randrange_i64
This commit is contained in:
parent
500fd47986
commit
f911933588
@ -62,4 +62,10 @@ static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;}
|
|||||||
static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT64_MIN); return -x;}
|
static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT64_MIN); return -x;}
|
||||||
static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > PTRDIFF_MIN); return -x;}
|
static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > PTRDIFF_MIN); return -x;}
|
||||||
|
|
||||||
|
static inline uint32_t guf_uabs_i32(int32_t x) {if (x >= 0) {return x;} else if (x == INT32_MIN) {return (uint32_t)INT32_MAX + 1;} else {return -x;}}
|
||||||
|
static inline uint64_t guf_uabs_i64(int64_t x) {if (x >= 0) {return x;} else if (x == INT64_MIN) {return (uint64_t)INT64_MAX + 1;} else {return -x;}}
|
||||||
|
|
||||||
|
static inline uint32_t guf_absdiff_i32(int32_t a, int32_t b) {return a > b ? (uint32_t)a - (uint32_t)b : (uint32_t)b - (uint32_t)a;}
|
||||||
|
static inline uint64_t guf_absdiff_i64(int64_t a, int64_t b) {return a > b ? (uint64_t)a - (uint64_t)b : (uint64_t)b - (uint64_t)a;}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -223,7 +223,7 @@ GUF_FN_KEYWORDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int
|
|||||||
const unsigned rand_max_shift = 1;
|
const unsigned rand_max_shift = 1;
|
||||||
const uint64_t rand_max = GUF_RAND_MAX >> rand_max_shift; // 2^63 - 1
|
const uint64_t rand_max = GUF_RAND_MAX >> rand_max_shift; // 2^63 - 1
|
||||||
|
|
||||||
const uint64_t delta = max - min;
|
const uint64_t delta = guf_absdiff_i64(max, min);
|
||||||
if (delta > rand_max) {
|
if (delta > rand_max) {
|
||||||
guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange_i64: interval [min, max] larger than INT64_MAX"));
|
guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange_i64: interval [min, max] larger than INT64_MAX"));
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#define GUF_RAND32_MAX UINT32_MAX
|
#define GUF_RAND32_MAX UINT32_MAX
|
||||||
|
|
||||||
typedef struct guf_randstate32 { // State for xoshiro256** 1.0
|
typedef struct guf_randstate32 { // State for xoshiro128** 1.1
|
||||||
uint32_t s[4];
|
uint32_t s[4];
|
||||||
} guf_randstate32;
|
} guf_randstate32;
|
||||||
|
|
||||||
@ -66,7 +66,6 @@ GUF_FN_KEYWORDS void guf_randstate32_init(guf_randstate32 *state, uint64_t seed)
|
|||||||
|
|
||||||
if (!state->s[0] && !state->s[1] && !state->s[2] && !state->s[3]) { // State must not be only zeroes:
|
if (!state->s[0] && !state->s[1] && !state->s[2] && !state->s[3]) { // State must not be only zeroes:
|
||||||
state->s[0] = 0x9e3779b9; // arbitrary constant != 0
|
state->s[0] = 0x9e3779b9; // arbitrary constant != 0
|
||||||
|
|
||||||
seed = 0x9e3779b97f4a7c15;
|
seed = 0x9e3779b97f4a7c15;
|
||||||
split = guf_rand32_splitmix64(&seed);
|
split = guf_rand32_splitmix64(&seed);
|
||||||
state->s[0] = (uint32_t)split; // lower 32-bits
|
state->s[0] = (uint32_t)split; // lower 32-bits
|
||||||
@ -174,18 +173,19 @@ GUF_FN_KEYWORDS int32_t guf_rand32range_i32(guf_randstate32 *state, int32_t min,
|
|||||||
const unsigned rand_max_shift = 1;
|
const unsigned rand_max_shift = 1;
|
||||||
const uint32_t rand_max = GUF_RAND32_MAX >> rand_max_shift; // 2^32 - 1
|
const uint32_t rand_max = GUF_RAND32_MAX >> rand_max_shift; // 2^32 - 1
|
||||||
|
|
||||||
const uint32_t delta = max - min;
|
const uint32_t delta = guf_absdiff_i32(max, min);
|
||||||
if (delta > rand_max) {
|
if (delta > rand_max) {
|
||||||
guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange32_i32: interval [min, max] larger than INT32_MAX"));
|
guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange32_i32: interval [min, max] larger than INT32_MAX"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
cf. https://c-faq.com/lib/randrange.html (last-retrieved 2025-02-11)
|
cf. https://c-faq.com/lib/randrange.html (last-retrieved 2025-02-11)
|
||||||
https://stackoverflow.com/a/6852396 (last-retrieved 2025-02-11)
|
https://stackoverflow.com/a/6852396 (last-retrieved 2025-02-11)
|
||||||
*/
|
*/
|
||||||
const uint32_t num_rand_vals = rand_max + 1u; // 2^31
|
const uint32_t num_rand_vals = rand_max + 1u; // 2^31
|
||||||
const uint32_t num_bins = (delta + 1u);
|
const uint32_t num_bins = (delta + 1u);
|
||||||
|
|
||||||
const uint32_t bin_size = num_rand_vals / num_bins; // bin_size = floor(num_rand_vals / num_bins)
|
const uint32_t bin_size = num_rand_vals / num_bins; // bin_size = floor(num_rand_vals / num_bins)
|
||||||
const uint32_t limit = num_rand_vals - (num_rand_vals % num_bins); // limit == bin_size * num_bins
|
const uint32_t limit = num_rand_vals - (num_rand_vals % num_bins); // limit == bin_size * num_bins
|
||||||
GUF_ASSERT(limit == bin_size * num_bins);
|
GUF_ASSERT(limit == bin_size * num_bins);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user