From 6461906beb86c4583eb4e3f8bb1ed03221277f3e Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 13 Nov 2023 19:41:08 +0100 Subject: [PATCH] Cygwin: random: make random(3) functions thread-safe Add locking to the random(3) family of functions to gain thread-safety per POSIX. Use NetBSD version of the file as role-model. Reported-by: Bruno Haible Signed-off-by: Corinna Vinschen --- winsup/cygwin/random.cc | 47 +++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/winsup/cygwin/random.cc b/winsup/cygwin/random.cc index 163fc040c..b38fdc078 100644 --- a/winsup/cygwin/random.cc +++ b/winsup/cygwin/random.cc @@ -29,6 +29,14 @@ #define __INSIDE_CYGWIN__ +#include "winsup.h" + +SRWLOCK NO_COPY rndlock = SRWLOCK_INIT; +# define __random_lock() { if (__isthreaded) \ + AcquireSRWLockExclusive (&rndlock); } +# define __random_unlock() { if (__isthreaded) \ + ReleaseSRWLockExclusive (&rndlock); } + extern "C" { #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95"; @@ -248,6 +256,8 @@ static inline uint32_t good_rand (int32_t x) #endif /* !USE_WEAK_SEEDING */ } +static long __random_unlocked(); + /* * srandom: * @@ -260,8 +270,8 @@ static inline uint32_t good_rand (int32_t x) * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] * for default usage relies on values produced by this routine. */ -void -srandom(unsigned x) +static void +__srandom_unlocked(unsigned x) { int i, lim; @@ -276,7 +286,15 @@ srandom(unsigned x) lim = 10 * rand_deg; } for (i = 0; i < lim; i++) - (void)random(); + (void)__random_unlocked(); +} + +void +srandom(unsigned x) +{ + __random_lock(); + __srandom_unlocked(x); + __random_unlock(); } /* @@ -350,6 +368,7 @@ initstate(unsigned seed, /* seed for R.N.G. */ char *ostate = (char *)(&state[-1]); uint32_t *int_arg_state = (uint32_t *)arg_state; + __random_lock(); if (rand_type == TYPE_0) state[-1] = rand_type; else @@ -358,6 +377,7 @@ initstate(unsigned seed, /* seed for R.N.G. */ (void)fprintf(stderr, "random: not enough state (%lu bytes); ignored.\n", (unsigned long) n); + __random_unlock(); return(0); } if (n < BREAK_1) { @@ -383,11 +403,12 @@ initstate(unsigned seed, /* seed for R.N.G. */ } state = int_arg_state + 1; /* first location */ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ - srandom(seed); + __srandom_unlocked(seed); if (rand_type == TYPE_0) int_arg_state[0] = rand_type; else int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type; + __random_unlock(); return(ostate); } @@ -418,6 +439,7 @@ setstate(char *arg_state /* pointer to state array */) uint32_t rear = new_state[0] / MAX_TYPES; char *ostate = (char *)(&state[-1]); + __random_lock(); if (rand_type == TYPE_0) state[-1] = rand_type; else @@ -442,6 +464,7 @@ setstate(char *arg_state /* pointer to state array */) fptr = &state[(rear + rand_sep) % rand_deg]; } end_ptr = &state[rand_deg]; /* set end_ptr too */ + __random_unlock(); return(ostate); } @@ -462,8 +485,8 @@ setstate(char *arg_state /* pointer to state array */) * * Returns a 31-bit random number. */ -long -random() +static long +__random_unlocked() { uint32_t i; uint32_t *f, *r; @@ -490,4 +513,16 @@ random() } return((long)i); } + +long +random() +{ + long r; + + __random_lock(); + r = __random_unlocked(); + __random_unlock(); + return (r); +} + } -- 2.43.5