From c23d573f29b40dc21606c413d0592c987b90f302 Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 29 May 2016 06:46:17 +0000 Subject: MFC: r300397 1) POSIX prohibits printing errors to stderr here and require returning NULL: "Upon successful completion, initstate() and setstate() shall return a pointer to the previous state array; otherwise, a null pointer shall be returned. Although some implementations of random() have written messages to standard error, such implementations do not conform to POSIX.1-2008." 2) Move error detections earlier to prevent state modifying. --- lib/libc/stdlib/random.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'lib/libc/stdlib') diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c index 580f26e3..f7b745e 100644 --- a/lib/libc/stdlib/random.c +++ b/lib/libc/stdlib/random.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include "un-namespace.h" @@ -341,15 +340,12 @@ initstate(unsigned long seed, char *arg_state, long n) char *ostate = (char *)(&state[-1]); uint32_t *int_arg_state = (uint32_t *)arg_state; + if (n < BREAK_0) + return (NULL); if (rand_type == TYPE_0) state[-1] = rand_type; else state[-1] = MAX_TYPES * (rptr - state) + rand_type; - if (n < BREAK_0) { - (void)fprintf(stderr, - "random: not enough state (%ld bytes); ignored.\n", n); - return (0); - } if (n < BREAK_1) { rand_type = TYPE_0; rand_deg = DEG_0; @@ -408,24 +404,23 @@ setstate(char *arg_state) uint32_t rear = new_state[0] / MAX_TYPES; char *ostate = (char *)(&state[-1]); - if (rand_type == TYPE_0) - state[-1] = rand_type; - else - state[-1] = MAX_TYPES * (rptr - state) + rand_type; switch(type) { case TYPE_0: case TYPE_1: case TYPE_2: case TYPE_3: case TYPE_4: - rand_type = type; - rand_deg = degrees[type]; - rand_sep = seps[type]; break; default: - (void)fprintf(stderr, - "random: state info corrupted; not changed.\n"); + return (NULL); } + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = MAX_TYPES * (rptr - state) + rand_type; + rand_type = type; + rand_deg = degrees[type]; + rand_sep = seps[type]; state = new_state + 1; if (rand_type != TYPE_0) { rptr = &state[rear]; -- cgit v1.1 From 4ab0fcf85bd26f3eaf7a2f8693ed80e89d2be762 Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 5 Jun 2016 13:39:31 +0000 Subject: MFC: r300953 1) Unifdef USE_WEAK_SEEDING it is too obsolete to support and makes reading harder. 2) ACM paper require seed to be in [1, 2^31-2] range, so use the same range shifting as already done for rand(3). Also protect srandomdev() + TYPE_0 case (non default) from negative seeds. 3) Don't check for valid "type" range in setstate(), it is always valid as calculated. Instead add a check that rear pointer not exceeed end pointer. MFC: r300965 Micro optimize: C standard guarantees that right shift for unsigned value fills left bits with zero, and we have exact 32bit unsigned value (uint32_t), so there is no reason to add "& 0x7fffffff" here. --- lib/libc/stdlib/random.c | 62 ++++++++++++------------------------------------ 1 file changed, 15 insertions(+), 47 deletions(-) (limited to 'lib/libc/stdlib') diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c index f7b745e..fe8fc86 100644 --- a/lib/libc/stdlib/random.c +++ b/lib/libc/stdlib/random.c @@ -137,11 +137,7 @@ __FBSDID("$FreeBSD$"); */ #define MAX_TYPES 5 /* max number of types above */ -#ifdef USE_WEAK_SEEDING -#define NSHUFF 0 -#else /* !USE_WEAK_SEEDING */ #define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */ -#endif /* !USE_WEAK_SEEDING */ static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; @@ -162,23 +158,12 @@ static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; static uint32_t randtbl[DEG_3 + 1] = { TYPE_3, -#ifdef USE_WEAK_SEEDING -/* Historic implementation compatibility */ -/* The random sequences do not vary much with the seed */ - 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, - 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, - 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, - 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, - 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, - 0x27fb47b9, -#else /* !USE_WEAK_SEEDING */ - 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05, - 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454, - 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471, - 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1, - 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41, - 0xf3bec5da -#endif /* !USE_WEAK_SEEDING */ + 0x2cf41758, 0x27bb3711, 0x4916d4d1, 0x7b02f59f, 0x9b8e28eb, 0xc0e80269, + 0x696f5c16, 0x878f1ff5, 0x52d9c07f, 0x916a06cd, 0xb50b3a20, 0x2776970a, + 0xee4eb2a6, 0xe94640ec, 0xb1d65612, 0x9d1ed968, 0x1043f6b7, 0xa3432a76, + 0x17eacbb9, 0x3c09e2eb, 0x4f8c2b3, 0x708a1f57, 0xee341814, 0x95d0e4d2, + 0xb06f216c, 0x8bd2e72e, 0x8f7c38d7, 0xcfc6a8fc, 0x2a59495, 0xa20d2a69, + 0xe29d12d1 }; /* @@ -215,16 +200,8 @@ static int rand_sep = SEP_3; static uint32_t *end_ptr = &randtbl[DEG_3 + 1]; static inline uint32_t -good_rand(int32_t x) +good_rand(uint32_t ctx) { -#ifdef USE_WEAK_SEEDING -/* - * Historic implementation compatibility. - * The random sequences do not vary much with the seed, - * even with overflowing. - */ - return (1103515245 * x + 12345); -#else /* !USE_WEAK_SEEDING */ /* * Compute x = (7^5 * x) mod (2^31 - 1) * wihout overflowing 31 bits: @@ -233,18 +210,17 @@ good_rand(int32_t x) * Park and Miller, Communications of the ACM, vol. 31, no. 10, * October 1988, p. 1195. */ - int32_t hi, lo; + int32_t hi, lo, x; - /* Can't be initialized with 0, so use another value. */ - if (x == 0) - x = 123459876; + /* Transform to [1, 0x7ffffffe] range. */ + x = (ctx % 0x7ffffffe) + 1; hi = x / 127773; lo = x % 127773; x = 16807 * lo - 2836 * hi; if (x < 0) x += 0x7fffffff; - return (x); -#endif /* !USE_WEAK_SEEDING */ + /* Transform to [0, 0x7ffffffd] range. */ + return (x - 1); } /* @@ -404,16 +380,8 @@ setstate(char *arg_state) uint32_t rear = new_state[0] / MAX_TYPES; char *ostate = (char *)(&state[-1]); - switch(type) { - case TYPE_0: - case TYPE_1: - case TYPE_2: - case TYPE_3: - case TYPE_4: - break; - default: + if (type != TYPE_0 && rear >= degrees[type]) return (NULL); - } if (rand_type == TYPE_0) state[-1] = rand_type; else @@ -455,14 +423,14 @@ random(void) if (rand_type == TYPE_0) { i = state[0]; - state[0] = i = (good_rand(i)) & 0x7fffffff; + state[0] = i = good_rand(i); } else { /* * Use local variables rather than static variables for speed. */ f = fptr; r = rptr; *f += *r; - i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */ + i = *f >> 1; /* chucking least random bit */ if (++f >= end_ptr) { f = state; ++r; -- cgit v1.1 From 199f28605719d4605c984cbf1df952f98c347a42 Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 5 Jun 2016 14:04:54 +0000 Subject: Prepare for merge of r300956. One year old r288030 which fix prototypes can't be merged without conflicts and require merging of other versions too and I don't want to go deep in that unmerged commits chain. --- lib/libc/stdlib/rand.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib/libc/stdlib') diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c index 4f4aa8d..b8871a2 100644 --- a/lib/libc/stdlib/rand.c +++ b/lib/libc/stdlib/rand.c @@ -111,14 +111,13 @@ static u_long next = #endif int -rand() +rand(void) { return (do_rand(&next)); } void -srand(seed) -u_int seed; +srand(u_int seed) { next = seed; #ifndef USE_WEAK_SEEDING @@ -136,7 +135,7 @@ u_int seed; * data from the kernel. */ void -sranddev() +sranddev(void) { int mib[2]; size_t len; -- cgit v1.1 From 29301f8121c8d897630c280668ea9a3c61b1f7d2 Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 5 Jun 2016 14:31:36 +0000 Subject: MFC: r300956 1) Unifdef USE_WEAK_SEEDING since it is too obsolete to support and makes reading hard. 2) Instead of doing range transformation in each and every function here, do it single time directly in do_rand(). One "mod" operation overhead is not a big deal, but the code looks nicer and possible future functions additions or PRNG change do not miss range transformations neither have unneeded ones. 3) Use POSIX argument types for visible functions (cosmetic). --- lib/libc/stdlib/rand.c | 52 +++++++++++--------------------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) (limited to 'lib/libc/stdlib') diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c index b8871a2..6125b1a 100644 --- a/lib/libc/stdlib/rand.c +++ b/lib/libc/stdlib/rand.c @@ -49,14 +49,6 @@ __FBSDID("$FreeBSD$"); static int do_rand(unsigned long *ctx) { -#ifdef USE_WEAK_SEEDING -/* - * Historic implementation compatibility. - * The random sequences do not vary much with the seed, - * even with overflowing. - */ - return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1)); -#else /* !USE_WEAK_SEEDING */ /* * Compute x = (7^5 * x) mod (2^31 - 1) * without overflowing 31 bits: @@ -67,48 +59,34 @@ do_rand(unsigned long *ctx) */ long hi, lo, x; - /* Must be in [1, 0x7ffffffe] range at this point. */ - hi = *ctx / 127773; - lo = *ctx % 127773; + /* Transform to [1, 0x7ffffffe] range. */ + x = (*ctx % 0x7ffffffe) + 1; + hi = x / 127773; + lo = x % 127773; x = 16807 * lo - 2836 * hi; if (x < 0) x += 0x7fffffff; - *ctx = x; /* Transform to [0, 0x7ffffffd] range. */ - return (x - 1); -#endif /* !USE_WEAK_SEEDING */ + x--; + *ctx = x; + return (x); } int -rand_r(unsigned int *ctx) +rand_r(unsigned *ctx) { u_long val; int r; -#ifdef USE_WEAK_SEEDING val = *ctx; -#else - /* Transform to [1, 0x7ffffffe] range. */ - val = (*ctx % 0x7ffffffe) + 1; -#endif r = do_rand(&val); - -#ifdef USE_WEAK_SEEDING - *ctx = (unsigned int)val; -#else - *ctx = (unsigned int)(val - 1); -#endif + *ctx = (unsigned)val; return (r); } -static u_long next = -#ifdef USE_WEAK_SEEDING - 1; -#else - 2; -#endif +static u_long next = 1; int rand(void) @@ -117,13 +95,9 @@ rand(void) } void -srand(u_int seed) +srand(unsigned seed) { next = seed; -#ifndef USE_WEAK_SEEDING - /* Transform to [1, 0x7ffffffe] range. */ - next = (next % 0x7ffffffe) + 1; -#endif } @@ -145,10 +119,6 @@ sranddev(void) mib[0] = CTL_KERN; mib[1] = KERN_ARND; sysctl(mib, 2, (void *)&next, &len, NULL, 0); -#ifndef USE_WEAK_SEEDING - /* Transform to [1, 0x7ffffffe] range. */ - next = (next % 0x7ffffffe) + 1; -#endif } -- cgit v1.1 From 1040e2abb6d69c17df9ac2b20ed5a6615e11d6f9 Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 5 Jun 2016 16:21:53 +0000 Subject: MFC: r301448 Reflect error indication according to POSIX and what those functions currently do. --- lib/libc/stdlib/random.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/libc/stdlib') diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3 index dc8e961..35b0aa1 100644 --- a/lib/libc/stdlib/random.3 +++ b/lib/libc/stdlib/random.3 @@ -175,8 +175,8 @@ If .Fn initstate is called with less than 8 bytes of state information, or if .Fn setstate -detects that the state information has been garbled, error -messages are printed on the standard error output. +detects that the state information has been garbled, +NULL is returned. .Sh SEE ALSO .Xr arc4random 3 , .Xr lrand48 3 , -- cgit v1.1 From 704e666406f9401fa4d34ab536981c2f7837ddf7 Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 5 Jun 2016 18:11:52 +0000 Subject: MFC: r301115 Don't use fixup for C99 and up, the compiler result is already correct. Suggested by: bde --- lib/libc/stdlib/div.c | 2 ++ lib/libc/stdlib/imaxdiv.c | 2 ++ lib/libc/stdlib/ldiv.c | 2 ++ lib/libc/stdlib/lldiv.c | 2 ++ 4 files changed, 8 insertions(+) (limited to 'lib/libc/stdlib') diff --git a/lib/libc/stdlib/div.c b/lib/libc/stdlib/div.c index 7dfe553..0bafbe6 100644 --- a/lib/libc/stdlib/div.c +++ b/lib/libc/stdlib/div.c @@ -46,6 +46,7 @@ div(num, denom) r.quot = num / denom; r.rem = num % denom; +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) /* * The ANSI standard says that |r.quot| <= |n/d|, where * n/d is to be computed in infinite precision. In other @@ -73,5 +74,6 @@ div(num, denom) r.quot++; r.rem -= denom; } +#endif return (r); } diff --git a/lib/libc/stdlib/imaxdiv.c b/lib/libc/stdlib/imaxdiv.c index 7dae467..adcab0b 100644 --- a/lib/libc/stdlib/imaxdiv.c +++ b/lib/libc/stdlib/imaxdiv.c @@ -37,9 +37,11 @@ imaxdiv(intmax_t numer, intmax_t denom) retval.quot = numer / denom; retval.rem = numer % denom; +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) if (numer >= 0 && retval.rem < 0) { retval.quot++; retval.rem -= denom; } +#endif return (retval); } diff --git a/lib/libc/stdlib/ldiv.c b/lib/libc/stdlib/ldiv.c index 0ec98e6..745c566 100644 --- a/lib/libc/stdlib/ldiv.c +++ b/lib/libc/stdlib/ldiv.c @@ -48,9 +48,11 @@ ldiv(num, denom) r.quot = num / denom; r.rem = num % denom; +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) if (num >= 0 && r.rem < 0) { r.quot++; r.rem -= denom; } +#endif return (r); } diff --git a/lib/libc/stdlib/lldiv.c b/lib/libc/stdlib/lldiv.c index b34b65e..197b48f 100644 --- a/lib/libc/stdlib/lldiv.c +++ b/lib/libc/stdlib/lldiv.c @@ -37,9 +37,11 @@ lldiv(long long numer, long long denom) retval.quot = numer / denom; retval.rem = numer % denom; +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) if (numer >= 0 && retval.rem < 0) { retval.quot++; retval.rem -= denom; } +#endif return (retval); } -- cgit v1.1