Submitted By: Robert Connolly (ashes) Date: 2007-06-11 Initial Package Version: 3.2 Upstream Status: Submitted - http://www.mail-archive.com/bug-bash%40gnu.org/msg02718.html Origin: The idea came from Debian's Bash random.dpatch. See Note below. Description: This patch uses ./configure to search for arc4random() and use them with the "$RANDOM" Bash variable if found. *** Note *** The Bash manual page states: RANDOM Each time this parameter is referenced, a random integer between 0 and 32767 is generated. The sequence of random numbers may be initialized by assigning a value to RANDOM. If RANDOM is unset, it loses its special properties, even if it is subsequently reset. Coincidentally the Korn shell has the exact same behavior, but this is not defined by Posix standards. In all cases `echo $RANDOM` will change each time, if 'RANDOM' is not initialized. The vanilla Bash uses OLD_RANDOM+getpid()+gettimeofday(). This patch uses arc4random() when 'RANDOM' is not initialized, which makes the returned value much more difficult to predict. Vanilla Bash, and the Bash using this patch: $ RANDOM=1 $ echo $RANDOM 16838 $ RANDOM=1 $ echo $RANDOM 16838 $ RANDOM=1 $ echo $RANDOM 16838 $ RANDOM=2 $ echo $RANDOM 908 $ RANDOM=3 $ echo $RANDOM 17747 $ RANDOM=2 $ echo $RANDOM 908 This is the documented and expected behavior of the shell. Any Bash, assuming the versions are the same, should produce "17747" if 'RANDOM=3', and so on. From the Debian random patch: $ RANDOM=1 $ echo $RANDOM 17767 $ RANDOM=1 $ echo $RANDOM 9158 $ RANDOM=1 $ echo $RANDOM 17767 $ RANDOM=1 $ echo $RANDOM 9158 This breaks the expected behavior. diff -Naur bash-3.2.orig/config.h.in bash-3.2/config.h.in --- bash-3.2.orig/config.h.in 2006-09-12 20:00:54.000000000 +0000 +++ bash-3.2/config.h.in 2007-04-26 04:49:04.000000000 +0000 @@ -496,6 +496,9 @@ /* Presence of system and C library functions. */ +/* Define if you have the arc4random function. */ +#undef HAVE_ARC4RANDOM + /* Define if you have the asprintf function. */ #undef HAVE_ASPRINTF diff -Naur bash-3.2.orig/configure bash-3.2/configure --- bash-3.2.orig/configure 2006-09-26 15:06:01.000000000 +0000 +++ bash-3.2/configure 2007-04-26 04:53:44.000000000 +0000 @@ -14542,6 +14542,109 @@ +for ac_func in arc4random +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + diff -Naur bash-3.2.orig/configure.in bash-3.2/configure.in --- bash-3.2.orig/configure.in 2006-09-26 15:05:45.000000000 +0000 +++ bash-3.2/configure.in 2007-04-26 04:49:26.000000000 +0000 @@ -748,6 +748,9 @@ AC_FUNC_MKTIME +dnl Checks for the arc4random function +AC_CHECK_FUNCS(arc4random) + dnl dnl Checks for lib/intl and related code (uses some of the output from dnl AM_GNU_GETTEXT) diff -Naur bash-3.2.orig/variables.c bash-3.2/variables.c --- bash-3.2.orig/variables.c 2006-09-08 17:33:32.000000000 +0000 +++ bash-3.2/variables.c 2007-04-26 04:53:27.000000000 +0000 @@ -1188,7 +1188,11 @@ /* Reset for command and process substitution. */ if (subshell_environment && seeded_subshell == 0) { +#if defined(HAVE_ARC4RANDOM) + sbrand (arc4random()); +#else sbrand (rseed + getpid() + NOW); +#endif seeded_subshell = 1; }