Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace usage of rand_r with nrand48 #817

Merged
merged 4 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ANNOUNCE
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,8 @@ New features in shell variables:

- TIMEFORMAT now supports a precision of up to six places after the decimal
point. The default precision for format directives remains 3.

- The $RANDOM pseudorandom numbers are now generated by nrand48(3) instead
of rand_r(3). Since POSIX specifies a particular pseudorandom generator
for nrand48, this means the same pseudorandom sequence should now be
generated on all platforms if RANDOM is assigned the same seed value.
7 changes: 7 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ This documents significant changes in the dev branch of ksh 93u+m.
For full details, see the git log at: https://github.com/ksh93/ksh
Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.

2025-01-15:

- [v1.1] The $RANDOM pseudorandom numbers are now generated by nrand48(3)
instead of rand_r(3). Since POSIX specifies a particular pseudorandom
generator for nrand48, this means the same pseudorandom sequence should now
be generated on all platforms if RANDOM is assigned the same seed value.

2025-01-08:

- Fixed buggy emacs mode behaviour on exceeding the maximum line length.
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/variables.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
struct rand
{
Namfun_t hdr;
unsigned int rand_seed;
unsigned short rand_seed[3];
int32_t rand_last;
};
extern void sh_reseed_rand(struct rand *);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <ast_release.h>
#include "git.h"

#define SH_RELEASE_DATE "2025-01-08" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_DATE "2025-01-15" /* must be in this format for $((.sh.version)) */
/*
* This comment keeps SH_RELEASE_DATE a few lines away from SH_RELEASE_SVER to avoid
* merge conflicts when cherry-picking dev branch commits onto a release branch.
Expand Down
51 changes: 11 additions & 40 deletions src/cmd/ksh93/sh/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,38 +623,15 @@ static Sfdouble_t nget_seconds(Namval_t* np, Namfun_t *fp)
return dtime(&tp) - offset;
}

#if !_lib_rand_r
#undef RAND_MAX
#define RAND_MAX 0x7fffffff
#define rand_r _ksh_rand_r
/*
* rand_r(3) fallback nicked from FreeBSD libc.
* License: BSD 3-clause. See the COPYRIGHT file.
* Not to be confused with actual randomness!
*
* Compute x = (7^5 * x) mod (2^31 - 1)
* without overflowing 31 bits:
* (2^31 - 1) = 127773 * (7^5) + 2836
* From "Random number generators: good ones are hard to find",
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
* Seeds the rand stucture using the same algorithm as srand48()
*/
static int rand_r(unsigned int *seed)
{
long hi, lo, x;
/* Transform to [1, 0x7ffffffe] range. */
x = (*seed % 0x7ffffffe) + 1;
hi = x / 127773;
lo = x % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
/* Transform to [0, 0x7ffffffd] range. */
x--;
*seed = x;
return x;
}
#endif /* !_lib_rand_r */
static void seed_rand_uint(struct rand *rp, unsigned int seed)
{
rp->rand_seed[0] = 0x330e; /* Constant from POSIX spec. */
rp->rand_seed[1] = (unsigned short)seed;
rp->rand_seed[2] = (unsigned short)(seed >> 16);
}

/*
* These four functions are used to get and set the RANDOM variable
Expand All @@ -676,7 +653,7 @@ static void put_rand(Namval_t* np,const char *val,int flags,Namfun_t *fp)
n = *(Sfdouble_t*)val;
else
n = sh_arith(val);
rp->rand_seed = (unsigned int)n;
seed_rand_uint(rp, (unsigned int)n);
rp->rand_last = -1;
if(!np->nvalue)
np->nvalue = &rp->rand_last;
Expand All @@ -694,14 +671,8 @@ static Sfdouble_t nget_rand(Namval_t* np, Namfun_t *fp)
int32_t last = *lp;
sh_save_rand_seed(rp, 1);
do
#if RAND_MAX > (RANDMASK << 3)
/* don't use lower bits when rand_r() generates large numbers */
cur = (rand_r(&rp->rand_seed) >> 3) & RANDMASK;
#elif RAND_MAX > RANDMASK
cur = rand_r(&rp->rand_seed) & RANDMASK;
#else
cur = rand_r(&rp->rand_seed);
#endif
/* don't use lower bits when generating large numbers */
cur = (nrand48(rp->rand_seed) >> 3) & RANDMASK;
while(cur==last);
*lp = cur;
return (Sfdouble_t)cur;
Expand All @@ -715,7 +686,7 @@ static char* get_rand(Namval_t* np, Namfun_t *fp)

void sh_reseed_rand(struct rand *rp)
{
rp->rand_seed = arc4random();
seed_rand_uint(rp, arc4random());
rp->rand_last = -1;
}

Expand Down
6 changes: 3 additions & 3 deletions src/cmd/ksh93/sh/subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static struct subshell
int cpipe;
char subshare;
char comsub;
unsigned int rand_seed; /* parent shell $RANDOM seed */
unsigned short rand_seed[3]; /* parent shell $RANDOM seed */
int rand_last; /* last random number from $RANDOM in parent shell */
char rand_state; /* 0 means sp->rand_seed hasn't been set, 1 is the opposite */
uint32_t srand_upper_bound; /* parent shell's upper bound for $SRANDOM */
Expand Down Expand Up @@ -226,7 +226,7 @@ void sh_save_rand_seed(struct rand *rp, int reseed)
struct subshell *sp = subshell_data;
if(!sh.subshare && sp && !sp->rand_state)
{
sp->rand_seed = rp->rand_seed;
memcpy(sp->rand_seed, rp->rand_seed, sizeof sp->rand_seed);
sp->rand_last = rp->rand_last;
sp->rand_state = 1;
if(reseed)
Expand Down Expand Up @@ -886,7 +886,7 @@ Sfio_t *sh_subshell(Shnode_t *t, volatile int flags, int comsub)
rp = (struct rand*)RANDNOD->nvfun;
if(sp->rand_state)
{
rp->rand_seed = sp->rand_seed;
memcpy(rp->rand_seed, sp->rand_seed, sizeof rp->rand_seed);
rp->rand_last = sp->rand_last;
}
/* restore $SRANDOM upper bound */
Expand Down
15 changes: 1 addition & 14 deletions src/lib/libast/Mamfile
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,6 @@ make install virtual
prev FEATURE/lib
exec - cp -f %{<} %{@}
done
make ast_mmap.h
prev FEATURE/mmap
exec - cp -f %{<} %{@}
done
make ast_fs.h
prev FEATURE/fs
exec - cp -f %{<} %{@}
Expand Down Expand Up @@ -4295,15 +4291,6 @@ make install virtual
exec - compile %{<}
done

make astcopy.o
make port/astcopy.c
prev include/ls.h
prev ast_mmap.h
prev include/ast.h
done
exec - compile %{<}
done

make astconf.o
make port/astconf.c
prev FEATURE/libpath
Expand Down Expand Up @@ -4480,7 +4467,7 @@ make install virtual
done
done
note * ...generated headers
loop HDR ast_release ast_standards ast_common ast_lib ast_sys lc align sig tmx tv ast_api ast_ccode ast_fcntl ast_float ast_fs ast_map ast_mmap ast_mode ast_ndbm ast_param ast_random ast_time ast_tty ast_limits ast_sizeof ast_dirent ast_iconv ast_nl_types ast_stdio ast_wchar ast_wctype
loop HDR ast_release ast_standards ast_common ast_lib ast_sys lc align sig tmx tv ast_api ast_ccode ast_fcntl ast_float ast_fs ast_map ast_mode ast_ndbm ast_param ast_random ast_time ast_tty ast_limits ast_sizeof ast_dirent ast_iconv ast_nl_types ast_stdio ast_wchar ast_wctype
make %{INCLUDE_AST}/%{HDR}.h
prev %{HDR}.h
exec - cp -f %{<} %{@}
Expand Down
1 change: 0 additions & 1 deletion src/lib/libast/include/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ extern char* astgetconf(const char*, const char*, const char*, int, Error_f);
extern char* astconf(const char*, const char*, const char*);
extern Ast_confdisc_f astconfdisc(Ast_confdisc_f);
extern void astconflist(Sfio_t*, const char*, int, const char*);
extern off_t astcopy(int, int, off_t);
extern int astquery(int, const char*, ...);
extern void astwinsize(int, int*, int*);
#if _lib_sysconf
Expand Down
24 changes: 0 additions & 24 deletions src/lib/libast/man/ast.3
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ long astconf_long(\fIarg\fP);
unsigned long astconf_ulong(\fIarg\fP);
Ast_confdisc_t astconfdisc(Ast_confdisc_t new_notify);
void astconflist(Sfio_t* stream, const char* path, int flags);
off_t astcopy(int \fIrfd\fP, int \fIwfd\fP, off_t \fIn\fP);
int astquery(int \fIfd\fP, const char* \fIformat\fP , ...);
.EE
.SH DESCRIPTION
Expand Down Expand Up @@ -223,29 +222,6 @@ snarfed for input to the
.IR getconf (1)
command.
.PP
.L astcopy
efficiently copies up to
.I n
bytes from the file descriptor
.I rfd
to the file descriptor
.IR wfd .
The actual number of bytes copied is returned; \-1 is returned on error.
If
.I n
is 0 then an optimal number of bytes (with respect to both
.I rfd
and
.IR wfd )
is copied.
.PP
If possible
.IR mmap (2)
is used to do the transfer.
Some implementations may bypass user buffer copies usually required by the
.IR read (2)- write (2)
paradigm.
.PP
.L astquery
outputs an
.IR sfprintf (3)
Expand Down
86 changes: 0 additions & 86 deletions src/lib/libast/port/astcopy.c

This file was deleted.