From: Stuart Henderson Subject: Re: ksh(1), use arc4random_uniform(3) to calculate $RANDOM To: Biarder , Date: Fri, 22 May 2026 12:44:30 +0100 read about RANDOM in ksh(1), it is required that this give deterministic output in some cases -- Sent from a phone, apologies for poor formatting. On 22 May 2026 10:54:11 Biarder wrote: > Currently, ksh(1) uses rand(3) and modular arithmetic to calculate > $RANDOM. However, OpenBSD recommend using arc4random_uniform(3) > to calculate a uniform random integer because rand function is > predictable and also has modular bias when modulo operation is > performed. > > I passed all regress tests on OpenBSD 7.9 GENERIC.MP#495 amd64. > > Index: jobs.c > =================================================================== > RCS file: /cvs/src/bin/ksh/jobs.c,v > diff -u -p -r1.62 jobs.c > --- jobs.c 7 Jul 2020 10:33:58 -0000 1.62 > +++ jobs.c 22 May 2026 09:50:35 -0000 > @@ -528,8 +528,6 @@ exchild(struct op *t, int flags, volatil > } > > /* shell (parent) stuff */ > - /* Ensure next child gets a (slightly) different $RANDOM sequence */ > - change_random(); > if (!(flags & XPIPEO)) { /* last process in a job */ > /* YYY: Is this needed? (see also YYY above) > if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND))) > Index: sh.h > =================================================================== > RCS file: /cvs/src/bin/ksh/sh.h,v > diff -u -p -r1.78 sh.h > --- sh.h 5 Mar 2026 05:38:58 -0000 1.78 > +++ sh.h 22 May 2026 09:50:35 -0000 > @@ -598,7 +598,6 @@ char *skip_wdvarname(const char *, int); > int is_wdvarname(const char *, int); > int is_wdvarassign(const char *); > char ** makenv(void); > -void change_random(void); > int array_ref_len(const char *); > char * arrayname(const char *); > void set_array(const char *, int, char **); > Index: var.c > =================================================================== > RCS file: /cvs/src/bin/ksh/var.c,v > diff -u -p -r1.76 var.c > --- var.c 5 Mar 2026 05:40:37 -0000 1.76 > +++ var.c 22 May 2026 09:50:35 -0000 > @@ -880,17 +880,6 @@ makenv(void) > } > > /* > - * Called after a fork in parent to bump the random number generator. > - * Done to ensure children will not get the same random number sequence > - * if the parent doesn't use $RANDOM. > - */ > -void > -change_random(void) > -{ > - rand(); > -} > - > -/* > * handle special variables with side effects - PATH, SECONDS. > */ > > @@ -939,7 +928,7 @@ getspec(struct tbl *vp) > break; > case V_RANDOM: > vp->flag &= ~SPECIAL; > - setint(vp, (int64_t) (rand() & 0x7fff)); > + setint(vp, (int64_t) arc4random_uniform(0x8000)); > vp->flag |= SPECIAL; > break; > case V_HISTSIZE: