From: Chet Ramey Date: Tue, 28 May 2019 14:02:20 +0000 (-0400) Subject: commit bash-20190517 snapshot X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=376c9fe57c48d851396574fe11baae8b9274c952;p=thirdparty%2Fbash.git commit bash-20190517 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index adbd2b62a..0fc3f3927 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -64,7 +64,7 @@ parse.y 9/23 ---- -execute_command.c +execute_cmd.c - execute_in_subshell: call without_job_control for both job control and non-job-control builds to avoid waiting for last_made_pid inherited from parent shell. Related to fix from 8/4 to @@ -5889,8 +5889,7 @@ lib/readline/terminal.c configure.ac - - hpux: add -DTGETENT_BROKEN to LOCAL_CFLAGS. Still need to do this - in the readline configure.ac + - hpux: add -DTGETENT_BROKEN to LOCAL_CFLAGS execute_cmd.c - select_builtin: set executing_builtin around the call to read_builtin @@ -5903,3 +5902,75 @@ doc/bashref.texi - The Restricted Shell: add some language detailing the weaknesses of the restricted shell mode in isolation, inspired by a discussion on the zsh mailing list + + 5/15 + ---- +xmalloc.h + - malloc: define to sh_malloc to get file and line information from + malloc (not xmalloc) calls. From a suggestion by achurch@achurch.org + (Andrew Church) + +builtins/evalstring.c + - parse_and_execute: make sure the parser is not expanding an alias + before terminating the loop that processes characters in the string. + Fixes problem with -c commands that end with an alias reported by + Yu Kou + - should_suppress_fork: make sure that we don't try to optimize out a + fork if the parser is still expanding an alias + + 5/16 + ---- +lib/readline/misc.c + - rl_get_previous_history: if previous_history() returns NULL, only + free the saved history if we were the ones who saved it; leave any + existing saved history entry alone. Fixes problem with ^N not working + at the end of the history if we previously moved back to the start + of history + +lib/readline/histfile.c + - read_history_range: when reading until FROM lines with a history + file that has timestamps, make sure to skip to the end of the command + line corresponding to the FROMth line instead of leaving line_start + pointing to it, and keep track of the start of the last timestamp in + last_ts for use by the loop below. Fix for history -n bug reported + by HIROSE Masaaki + +lib/readline/display.c + - init_line_structures: if, for some reason, _rl_screenwidth ends up + bigger than the line_size default of 1024 (e.g., gdb's setting the + terminal width to 0), make sure line_size is at least _rl_screenwidth. + From a report by Tom de Vries + + 5/17 + ---- +variables.c + - brand: split the code into a function that generates a 32-bit value + given the last value in the sequence (intrand32) and a function that + returns a 16-bit random number (brand) + - seedrand: small change in hopes of adding slightly more entropy + - brand: modify the 16-bit version to XOR the top 16 bits of the 32-bit + seed with the bottom 16 bits and return the lower 15 bits of that + result as before. Based on an analysis by Andrew Church + + + 5/18 + ---- +variables.c + - genseed: break code that generates the 32-bit seed for the RNG into + a separate function; call from seedrand + - {brand32,sbrand32,seedrand32}: new 32-bit versions of the random + number generator functions that use the entire 32-bit internal value. + Prep for systems that don't have /dev/urandom or arc4random() + - perturb_rand32: shake up the 32-bit LCRNG in subshells + + 5/19 + ---- +variables.c + - get_urandom32: get a 32-bit random number by using the first one of + these that succeeds: reading from /dev/urandom (if available), + calling arc4random (if available), and using the internal 32-bit + RNG (always available) + - URANDOM: expand to a 32-bit random number. This is not a LCRNG, so + the numbers shouldn't have any relationship to previous returned + values. Assignments are accepted but have no effect on the sequence. + Not documented yet diff --git a/MANIFEST b/MANIFEST index 958a8a8d3..ac2d288f9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -862,6 +862,7 @@ tests/alias1.sub f tests/alias2.sub f tests/alias3.sub f tests/alias4.sub f +tests/alias5.sub f tests/alias.right f tests/appendop.tests f tests/appendop1.sub f diff --git a/builtins/evalstring.c b/builtins/evalstring.c index cadc9bc06..2f13a66ae 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -91,6 +91,7 @@ should_suppress_fork (command) return (startup_state == 2 && parse_and_execute_level == 1 && running_trap == 0 && *bash_input.location.string == '\0' && + parser_expanding_alias () == 0 && command->type == cm_simple && signal_is_trapped (EXIT_TRAP) == 0 && signal_is_trapped (ERROR_TRAP) == 0 && @@ -105,6 +106,7 @@ can_optimize_connection (command) COMMAND *command; { return (*bash_input.location.string == '\0' && + parser_expanding_alias () == 0 && (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') && command->value.Connection->second->type == cm_simple); } @@ -290,7 +292,7 @@ parse_and_execute (string, from_file, flags) with_input_from_string (string, from_file); clear_shell_input_line (); - while (*(bash_input.location.string)) + while (*(bash_input.location.string) || parser_expanding_alias ()) { command = (COMMAND *)NULL; @@ -545,7 +547,7 @@ parse_string (string, from_file, flags, endp) ostring = string; with_input_from_string (string, from_file); - while (*(bash_input.location.string)) + while (*(bash_input.location.string)) /* XXX - parser_expanding_alias () ? */ { command = (COMMAND *)NULL; diff --git a/config.h.in b/config.h.in index 8ae4db909..d8f5b8824 100644 --- a/config.h.in +++ b/config.h.in @@ -567,6 +567,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 --git a/configure b/configure index 21a81cb16..08a9c16d4 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac for Bash 5.0, version 5.009. +# From configure.ac for Bash 5.0, version 5.010. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for bash 5.0-maint. # @@ -13904,6 +13904,18 @@ _ACEOF fi done +for ac_func in arc4random +do : + ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" +if test "x$ac_cv_func_arc4random" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ARC4RANDOM 1 +_ACEOF + +fi +done + + ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" if test "x$ac_cv_func_getcwd" = xyes; then : $as_echo "#define HAVE_GETCWD 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 7bff7f915..400089cdc 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script. # You should have received a copy of the GNU General Public License # along with this program. If not, see . -AC_REVISION([for Bash 5.0, version 5.009])dnl +AC_REVISION([for Bash 5.0, version 5.010])dnl define(bashvers, 5.0) define(relstatus, maint) @@ -834,6 +834,8 @@ AC_CHECK_FUNCS(vasprintf asprintf) AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit) AC_CHECK_FUNCS(getpwent getpwnam getpwuid) AC_CHECK_FUNCS(mkstemp mkdtemp) +AC_CHECK_FUNCS(arc4random) + AC_REPLACE_FUNCS(getcwd memset) AC_REPLACE_FUNCS(strcasecmp strcasestr strerror strftime strnlen strpbrk strstr) AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax) diff --git a/lib/readline/display.c b/lib/readline/display.c index 4c6cc00ea..2716451f8 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -603,6 +603,9 @@ init_line_structures (int minsize) { register int n; + if (line_size <= _rl_screenwidth) /* XXX - for gdb */ + line_size = _rl_screenwidth + 1; + if (invisible_line == 0) /* initialize it */ { if (line_size < minsize) diff --git a/lib/readline/histfile.c b/lib/readline/histfile.c index aa34fe2db..dea897292 100644 --- a/lib/readline/histfile.c +++ b/lib/readline/histfile.c @@ -375,9 +375,11 @@ read_history_range (const char *filename, int from, int to) } has_timestamps = HIST_TIMESTAMP_START (buffer); - history_multiline_entries += has_timestamps && history_write_timestamps; + history_multiline_entries += has_timestamps && history_write_timestamps; /* Skip lines until we are at FROM. */ + if (has_timestamps) + last_ts = buffer; for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++) if (*line_end == '\n') { @@ -386,7 +388,18 @@ read_history_range (const char *filename, int from, int to) line. We should check more extensively here... */ if (HIST_TIMESTAMP_START(p) == 0) current_line++; + else + last_ts = p; line_start = p; + /* If we are at the last line (current_line == from) but we have + timestamps (has_timestamps), then line_start points to the + text of the last command, and we need to skip to its end. */ + if (current_line >= from && has_timestamps) + { + for (line_end = p; line_end < bufend && *line_end != '\n'; line_end++) + ; + line_start = (*line_end == '\n') ? line_end + 1 : line_end; + } } /* If there are lines left to gobble, then gobble them now. */ diff --git a/lib/readline/misc.c b/lib/readline/misc.c index 5e7979312..b49d61ac2 100644 --- a/lib/readline/misc.c +++ b/lib/readline/misc.c @@ -589,6 +589,7 @@ int rl_get_previous_history (int count, int key) { HIST_ENTRY *old_temp, *temp; + int had_saved_line; if (count < 0) return (rl_get_next_history (-count, key)); @@ -601,6 +602,7 @@ rl_get_previous_history (int count, int key) _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; /* If we don't have a line saved, then save this one. */ + had_saved_line = _rl_saved_line_for_history != 0; rl_maybe_save_line (); /* If the current line has changed, save the changes. */ @@ -624,7 +626,8 @@ rl_get_previous_history (int count, int key) if (temp == 0) { - _rl_free_saved_history_line (); + if (had_saved_line == 0) + _rl_free_saved_history_line (); rl_ding (); } else diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 0b0638107..c8bef8dd1 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/alias.right b/tests/alias.right index 29eb90daa..b588a72e4 100644 --- a/tests/alias.right +++ b/tests/alias.right @@ -34,3 +34,9 @@ bar bad 0 <|cat> +foo +bar +baz +foo +bar +baz diff --git a/tests/alias.tests b/tests/alias.tests index 6aa1218b0..cc59a0f57 100644 --- a/tests/alias.tests +++ b/tests/alias.tests @@ -40,3 +40,4 @@ ${THIS_SH} ./alias1.sub ${THIS_SH} ./alias2.sub ${THIS_SH} ./alias3.sub ${THIS_SH} ./alias4.sub +${THIS_SH} ./alias5.sub diff --git a/tests/alias5.sub b/tests/alias5.sub new file mode 100644 index 000000000..b7341349d --- /dev/null +++ b/tests/alias5.sub @@ -0,0 +1,15 @@ +# -c commands ending with multi-line aliases; post-bash-5.0 + +: ${THIS_SH:=./bash} + +${THIS_SH} -c "shopt -s expand_aliases &>/dev/null; +alias myalias='/bin/echo foo +echo bar +echo baz' +myalias" + +${THIS_SH} -c "shopt -s expand_aliases &>/dev/null; +alias myalias='echo foo +echo bar +echo baz' +myalias" diff --git a/tests/arith3.sub b/tests/arith3.sub index a510c7398..ce5416355 100644 --- a/tests/arith3.sub +++ b/tests/arith3.sub @@ -1,29 +1,31 @@ +# this depends on the sequence of random numbers from the internal LCRNG RANDOM=42 (( dice[RANDOM%6+1 + RANDOM%6+1]++ )) -echo ${dice[5]} +echo ${dice[6]} (( ++dice[RANDOM%6+1 + RANDOM%6+1] )) -echo ${dice[6]} +echo ${dice[7]} v=4 DIND=20 (( dice[DIND%6 + 1]=v )) echo ${dice[3]} +(( dice[DIND/v]+=2 )) RANDOM=42 (( dice[RANDOM%6+1 + RANDOM%6+1]+=v )) -echo ${dice[5]} +echo ${dice[6]} (( dice[RANDOM%6+1 + RANDOM%6+1]-=v )) -echo ${dice[6]} +echo ${dice[7]} (( dice[RANDOM%6+1 + RANDOM%6+1]+=2 )) -echo ${dice[11]} +echo ${dice[8]} (( dice[RANDOM%6+1 + RANDOM%6+1]*=2 )) -echo ${dice[11]} +echo ${dice[5]} unset dice1 dice2 RANDOM=42 diff --git a/variables.c b/variables.c index 83c4ce3a9..1256ab6b1 100644 --- a/variables.c +++ b/variables.c @@ -43,6 +43,7 @@ #endif #include "bashansi.h" #include "bashintl.h" +#include "filecntl.h" #define NEED_XTRACE_SET_DECL @@ -199,12 +200,24 @@ static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t, char *)); static SHELL_VAR *get_seconds __P((SHELL_VAR *)); static SHELL_VAR *init_seconds_var __P((void)); +static u_bits32_t intrand32 __P((u_bits32_t)); +static u_bits32_t genseed __P((void)); + static int brand __P((void)); static void sbrand __P((unsigned long)); /* set bash random number generator. */ static void seedrand __P((void)); /* seed generator randomly */ + +static u_bits32_t brand32 __P((void)); +static void sbrand32 __P((u_bits32_t)); +static void seedrand32 __P((void)); +static void perturb_rand32 __P((void)); +static u_bits32_t get_urandom32 __P((void)); + static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *)); static SHELL_VAR *get_random __P((SHELL_VAR *)); +static SHELL_VAR *get_urandom __P((SHELL_VAR *)); + static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t, char *)); static SHELL_VAR *get_lineno __P((SHELL_VAR *)); @@ -598,8 +611,9 @@ if (STREQ (name, "BASH_COMPAT")) } #endif /* HISTORY */ - /* Seed the random number generator. */ + /* Seed the random number generators. */ seedrand (); + seedrand32 (); /* Handle some "special" variables that we may have inherited from a parent shell. */ @@ -1321,17 +1335,10 @@ static u_bits32_t rseed = 1; static int last_random_value; static int seeded_subshell = 0; -#define BASH_RANDOM_16 1 - -#if BASH_RANDOM_16 -# define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */ -#else -# define BASH_RAND_MAX 0x7fffffff /* 32 bits */ -#endif - -/* Returns a pseudo-random number between 0 and 32767. */ -static int -brand () +/* Returns a 32-bit pseudo-random number. */ +static u_bits32_t +intrand32 (last) + u_bits32_t last; { /* Minimal Standard generator from "Random number generators: good ones are hard to find", @@ -1342,23 +1349,48 @@ brand () We split up the calculations to avoid overflow. - h = rseed / q; l = x - h * q; t = a * l - h * r + h = last / q; l = x - h * q; t = a * l - h * r m = 2147483647, a = 16807, q = 127773, r = 2836 There are lots of other combinations of constants to use; look at https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */ bits32_t h, l, t; + u_bits32_t ret; /* Can't seed with 0. */ - if (rseed == 0) - rseed = 123459876; - h = rseed / 127773; - l = rseed - (127773 * h); + ret = (last == 0) ? 123459876 : last; + h = ret / 127773; + l = ret - (127773 * h); t = 16807 * l - 2836 * h; - rseed = (t < 0) ? t + 0x7fffffff : t; + ret = (t < 0) ? t + 0x7fffffff : t; + + return (ret); +} + +static u_bits32_t +genseed () +{ + struct timeval tv; + u_bits32_t iv; - return ((unsigned int)(rseed & BASH_RAND_MAX)); /* was % BASH_RAND_MAX+1 */ + gettimeofday (&tv, NULL); + iv = (u_bits32_t)seedrand; /* let the compiler truncate */ + iv = tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ iv; + return (iv); +} + +#define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */ + +/* Returns a pseudo-random number between 0 and 32767. */ +static int +brand () +{ + unsigned int ret; + + rseed = intrand32 (rseed); + ret = (rseed >> 16) ^ (rseed & 65535); + return (ret & BASH_RAND_MAX); } /* Set the random number generator seed to SEED. */ @@ -1373,16 +1405,88 @@ sbrand (seed) static void seedrand () { - struct timeval tv; - SHELL_VAR *v; + u_bits32_t iv; - gettimeofday (&tv, NULL); -#if 0 - v = find_variable ("BASH_VERSION"); - sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid () ^ ((u_bits32_t)&v & 0x7fffffff)); + iv = genseed (); + sbrand (iv); +} + +static u_bits32_t rseed32 = 1073741823; +static int last_rand32; + +static int urandfd = -1; + +#define BASH_RAND32_MAX 0x7fffffff /* 32 bits */ + +/* Returns a 32-bit pseudo-random number between 0 and 4294967295. */ +static u_bits32_t +brand32 () +{ + u_bits32_t ret; + + rseed32 = intrand32 (rseed32); + return (rseed32 & BASH_RAND32_MAX); +} + +static void +sbrand32 (seed) + u_bits32_t seed; +{ + rseed32 = seed; + last_rand32 = seed; +} + +static void +seedrand32 () +{ + u_bits32_t iv; + + iv = genseed (); + sbrand32 (iv); +} + +static void +perturb_rand32 () +{ + rseed32 ^= genseed (); +} + +/* Force another attempt to open /dev/urandom on the next call to get_urandom32 */ +void +urandom_close () +{ + if (urandfd >= 0) + close (urandfd); + urandfd = -1; +} + +static u_bits32_t +get_urandom32 () +{ + u_bits32_t ret; + int n; + static int urand_unavail = 0; + + if (urandfd == -1 && urand_unavail == 0) + { + urandfd = open ("/dev/urandom", O_RDONLY, 0); + if (urandfd >= 0) + SET_CLOSE_ON_EXEC (urandfd); + else + urand_unavail = 1; + } + if (urandfd >= 0 && (n = read (urandfd, (char *)&ret, sizeof (ret))) == sizeof (ret)) + return (last_rand32 = ret); +#if defined (HAVE_ARC4RANDOM) + ret = arc4random (); #else - sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ current_user.gid); + if (subshell_environment) + perturb_rand32 (); + do + ret = brand32 (); + while (ret == last_rand32); #endif + return (last_rand32 = ret); } static SHELL_VAR * @@ -1414,7 +1518,8 @@ get_random_number () do rv = brand (); while (rv == last_random_value); - return rv; + + return (last_random_value = rv); } static SHELL_VAR * @@ -1425,7 +1530,23 @@ get_random (var) char *p; rv = get_random_number (); - last_random_value = rv; + p = itos (rv); + + FREE (value_cell (var)); + + VSETATTR (var, att_integer); + var_setvalue (var, p); + return (var); +} + +static SHELL_VAR * +get_urandom (var) + SHELL_VAR *var; +{ + u_bits32_t rv; + char *p; + + rv = get_urandom32 (); p = itos (rv); FREE (value_cell (var)); @@ -1919,6 +2040,8 @@ initialize_dynamic_variables () INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random); VSETATTR (v, att_integer); + INIT_DYNAMIC_VAR ("URANDOM", (char *)NULL, get_urandom, (sh_var_assign_func_t *)NULL); + VSETATTR (v, att_integer); INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno); VSETATTR (v, att_integer|att_regenerate); diff --git a/xmalloc.h b/xmalloc.h index bea71fdd6..083fd7a4a 100644 --- a/xmalloc.h +++ b/xmalloc.h @@ -53,6 +53,14 @@ extern void sh_xfree __P((void *, const char *, int)); #undef free #endif #define free(x) sh_xfree((x), __FILE__, __LINE__) + +extern PTR_T sh_malloc __P((size_t, const char *, int)); + +#ifdef malloc +#undef malloc +#endif +#define malloc(x) sh_malloc((x), __FILE__, __LINE__) + #endif /* USING_BASH_MALLOC */ #endif /* _XMALLOC_H_ */