1) POSIX requires rand(3) return values to be in the [0, RAND_MAX] range,
but ACM formula we use have internal state (and return value) in the [1, 0x7ffffffe] range, so our RAND_MAX (0x7fffffff) is never reached because it is off by one, zero is not reached too. Correct both RAND_MAX and rand(3) return value, shifting last one to the 0 by 1 subtracted, resulting POSIXed [0, 0x7ffffffd(=new RAND_MAX)] range. 2) Add a checks for not overflowing on too big seeds. It may happens on the machines, where sizeof(unsigned int) > 32 bits. Reviewed by: bde [1] MFC after: 2 weeks
This commit is contained in:
parent
6f691f7ee1
commit
476d9314d6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=252608
@ -69,7 +69,7 @@ typedef struct {
|
|||||||
#define EXIT_FAILURE 1
|
#define EXIT_FAILURE 1
|
||||||
#define EXIT_SUCCESS 0
|
#define EXIT_SUCCESS 0
|
||||||
|
|
||||||
#define RAND_MAX 0x7fffffff
|
#define RAND_MAX 0x7ffffffd
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
#ifdef _XLOCALE_H_
|
#ifdef _XLOCALE_H_
|
||||||
|
@ -67,15 +67,15 @@ do_rand(unsigned long *ctx)
|
|||||||
*/
|
*/
|
||||||
long hi, lo, x;
|
long hi, lo, x;
|
||||||
|
|
||||||
/* Can't be initialized with 0, so use another value. */
|
/* Must be in [1, 0x7ffffffe] range at this point. */
|
||||||
if (*ctx == 0)
|
|
||||||
*ctx = 123459876;
|
|
||||||
hi = *ctx / 127773;
|
hi = *ctx / 127773;
|
||||||
lo = *ctx % 127773;
|
lo = *ctx % 127773;
|
||||||
x = 16807 * lo - 2836 * hi;
|
x = 16807 * lo - 2836 * hi;
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
x += 0x7fffffff;
|
x += 0x7fffffff;
|
||||||
return ((*ctx = x) % ((u_long)RAND_MAX + 1));
|
*ctx = x;
|
||||||
|
/* Transform to [0, 0x7ffffffd] range. */
|
||||||
|
return (x - 1);
|
||||||
#endif /* !USE_WEAK_SEEDING */
|
#endif /* !USE_WEAK_SEEDING */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +84,10 @@ int
|
|||||||
rand_r(unsigned int *ctx)
|
rand_r(unsigned int *ctx)
|
||||||
{
|
{
|
||||||
u_long val = (u_long) *ctx;
|
u_long val = (u_long) *ctx;
|
||||||
|
#ifndef USE_WEAK_SEEDING
|
||||||
|
/* Transform to [1, 0x7ffffffe] range. */
|
||||||
|
val = (val % 0x7ffffffe) + 1;
|
||||||
|
#endif
|
||||||
int r = do_rand(&val);
|
int r = do_rand(&val);
|
||||||
|
|
||||||
*ctx = (unsigned int) val;
|
*ctx = (unsigned int) val;
|
||||||
@ -104,6 +108,10 @@ srand(seed)
|
|||||||
u_int seed;
|
u_int seed;
|
||||||
{
|
{
|
||||||
next = seed;
|
next = seed;
|
||||||
|
#ifndef USE_WEAK_SEEDING
|
||||||
|
/* Transform to [1, 0x7ffffffe] range. */
|
||||||
|
next = (next % 0x7ffffffe) + 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -125,6 +133,10 @@ sranddev()
|
|||||||
mib[0] = CTL_KERN;
|
mib[0] = CTL_KERN;
|
||||||
mib[1] = KERN_ARND;
|
mib[1] = KERN_ARND;
|
||||||
sysctl(mib, 2, (void *)&next, &len, NULL, 0);
|
sysctl(mib, 2, (void *)&next, &len, NULL, 0);
|
||||||
|
#ifndef USE_WEAK_SEEDING
|
||||||
|
/* Transform to [1, 0x7ffffffe] range. */
|
||||||
|
next = (next % 0x7ffffffe) + 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user