From af2a77fbbcf6e50edbc535eb3fd267bd3f4d1a14 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 8 May 2017 10:53:50 -0400 Subject: [PATCH] commit bash-20170505 snapshot --- CWRU/CWRU.chlog | 73 +++++++++++++++++++++++++++++++++++ builtins/builtin.def | 5 ++- builtins/read.def | 3 +- expr.c | 21 +++++++--- jobs.c | 4 +- lib/readline/bind.c | 5 ++- lib/readline/examples/rlcat.c | 2 +- lib/readline/kill.c | 2 +- lib/readline/misc.c | 7 +++- parse.y | 13 +++++-- tests/RUN-ONE-TEST | 2 +- tests/arith-for.right | 8 ++-- tests/arith-for.tests | 8 ++-- tests/comsub.tests | 2 +- 14 files changed, 125 insertions(+), 30 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 51e95ae3..7892ce94 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13767,3 +13767,76 @@ lib/glob/sm_loop.c matches beyond it. Look at https://research.swtch.com/glob for a longer explanation. This results in a significant speedup for globs with multiple instances of `*', especially with more than 4. + + 5/2 + --- +lib/readline/bind.c + - rl_translate_keyseq: make sure a trailing backslash in the key + sequence is preserved. Report from Eduardo Bustamante + + + 5/3 + --- +builtins/builtin.def + - builtin_builtin: make sure to set this_shell_builtin to the builtin + command being executed, overwriting `builtin'. Leave + last_shell_builtin alone. Fixes bug reported by Luiz Angelo Daros + de Luca + +jobs.c + - waitchld: modify change of 4/26 to run SIGCHLD traps even if job + control is not enabled + +lib/readline/misc.c + - rl_get_previous_history: if we didn't find a previous history entry + to use, call rl_maybe_unsave_line before returning because we + aren't going to use the saved line, and it has the same undo list + as rl_undo_list. Fixes fuzzing bug reported by Eduardo Bustamante + + - rl_get_{next,previous}_history: if there is no history list, don't + bother doing anything + + 5/4 + --- +expr.c + - popexp: if we error out due to stack underflow, make sure to zero out + expression and lasttp; they may contain undefined values we don't + want evalerror to print + - expr_unwind: handle expr_depth decrementing below zero + - evalexp: restore the old value of evalbuf even if we error and + longjmp; we may have called evalexp recursively + - evalerror: make sure expression is non-NULL before trying to print it. + These fix fuzzing bug reported by Eduardo Bustamante + , happens only in cases where we don't longjmp on + a fatal expansion error + + 5/5 + --- +parse.y + - read_token_word: when checking for a word that's a target of a + redirection, we can potentially call valid_array_reference, which + can end up calling the parser recursively. If it does that, we + need to make sure that yylval.word doesn't change, so we set it back + to the_word. Fixes another fuzzing bug + +parse.y + - arith_for_command: make syntax errors in the arithmetic for command + (signaled by make_arith_for_command returning NULL) more like + language syntax errors by calling YYERROR. Avoids complicated + attempts at error recovery and dealing with NULL returns from + command productions. Pointed out by Eduardo Bustamante + + +lib/readline/kill.c + - _rl_copy_to_kill_ring: make sure the current slot in the kill ring + has something in it, even if the last command was a kill, before + trying to modify it. Another fuzzing bug + + 5/6 + --- +builtins/read.def + - read_builtin: if we see a backslash when not in raw mode (not -r), + only back up `i' when we read the next character if we know we added + a CTLESC the last time through the loop (skip_ctlesc == 0), + especially if i == 0. Another fuzzing bug from Eduardo Bustamante + diff --git a/builtins/builtin.def b/builtins/builtin.def index 4867f3a8..b09246c4 100644 --- a/builtins/builtin.def +++ b/builtins/builtin.def @@ -1,7 +1,7 @@ This file is builtin.def, from which is created builtin.c. It implements the builtin "builtin" in Bash. -Copyright (C) 1987-2009 Free Software Foundation, Inc. +Copyright (C) 1987-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -70,7 +70,7 @@ builtin_builtin (list) function = find_shell_builtin (command); #endif /* !DISABLED_BUILTINS */ - if (!function) + if (function == 0) { sh_notbuiltin (command); return (EXECUTION_FAILURE); @@ -78,6 +78,7 @@ builtin_builtin (list) else { this_command_name = command; + this_shell_builtin = function; /* overwrite "builtin" as this builtin */ list = list->next; return ((*function) (list)); } diff --git a/builtins/read.def b/builtins/read.def index e6db4393..14da6a2f 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -627,7 +627,8 @@ read_builtin (list) pass_next = 0; if (c == '\n') { - i--; /* back up over the CTLESC */ + if (skip_ctlesc == 0 && i > 0) + i--; /* back up over the CTLESC */ if (interactive && input_is_tty && raw == 0) print_ps2 = 1; } diff --git a/expr.c b/expr.c index 0af5547b..1770cc00 100644 --- a/expr.c +++ b/expr.c @@ -283,8 +283,13 @@ popexp () { EXPR_CONTEXT *context; - if (expr_depth == 0) - evalerror (_("recursion stack underflow")); + if (expr_depth <= 0) + { + /* See the comment at the top of evalexp() for an explanation of why + this is done. */ + expression = lasttp = 0; + evalerror (_("recursion stack underflow")); + } context = expr_stack[--expr_depth]; @@ -307,7 +312,8 @@ expr_unwind () free (expr_stack[expr_depth]); } - free (expr_stack[expr_depth]); /* free the allocated EXPR_CONTEXT */ + if (expr_depth == 0) + free (expr_stack[expr_depth]); /* free the allocated EXPR_CONTEXT */ noeval = 0; /* XXX */ } @@ -397,6 +403,9 @@ evalexp (expr, flags, validp) expr_unwind (); + /* We copy in case we've called evalexp recursively */ + FASTCOPY (oevalbuf, evalbuf, sizeof (evalbuf)); + if (validp) *validp = 0; return (0); @@ -1456,11 +1465,11 @@ evalerror (msg) char *name, *t; name = this_command_name; - for (t = expression; whitespace (*t); t++) + for (t = expression; t && whitespace (*t); t++) ; internal_error (_("%s%s%s: %s (error token is \"%s\")"), - name ? name : "", name ? ": " : "", t, - msg, (lasttp && *lasttp) ? lasttp : ""); + name ? name : "", name ? ": " : "", + t ? t : "", msg, (lasttp && *lasttp) ? lasttp : ""); sh_longjmp (evalbuf, 1); } diff --git a/jobs.c b/jobs.c index ace3d922..b320b22f 100644 --- a/jobs.c +++ b/jobs.c @@ -3682,8 +3682,8 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc } /* Call a SIGCHLD trap handler for each child that exits, if one is set. */ - /* XXX - bash-5.0 adds posixly_correct test */ - if ((job_control || posixly_correct) && children_exited && + /* XXX - bash-5.0 removes test for job_control */ + if (children_exited && (signal_is_trapped (SIGCHLD) || trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER) && trap_list[SIGCHLD] != (char *)IGNORE_SIG) { diff --git a/lib/readline/bind.c b/lib/readline/bind.c index 117f3427..fef538b1 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -441,7 +441,10 @@ rl_translate_keyseq (const char *seq, char *array, int *len) c = seq[++i]; if (c == 0) - break; + { + array[l++] = '\\'; /* preserve trailing backslash */ + break; + } /* Handle \C- and \M- prefixes. */ if ((c == 'C' || c == 'M') && seq[i + 1] == '-') diff --git a/lib/readline/examples/rlcat.c b/lib/readline/examples/rlcat.c index fa9e06ff..b4942413 100644 --- a/lib/readline/examples/rlcat.c +++ b/lib/readline/examples/rlcat.c @@ -137,7 +137,7 @@ fcopy(fp) if (vflag && isascii ((unsigned char)c) && isprint((unsigned char)c) == 0) { x = rl_untranslate_keyseq (c); - if (fputs (x, stdout) != 0) + if (fputs (x, stdout) == EOF) return 1; } else if (putchar (c) == EOF) diff --git a/lib/readline/kill.c b/lib/readline/kill.c index 6875e3a1..65ab7e98 100644 --- a/lib/readline/kill.c +++ b/lib/readline/kill.c @@ -128,7 +128,7 @@ _rl_copy_to_kill_ring (char *text, int append) slot = rl_kill_ring_length - 1; /* If the last command was a kill, prepend or append. */ - if (_rl_last_command_was_kill && rl_editing_mode != vi_mode) + if (_rl_last_command_was_kill && rl_kill_ring[slot] && rl_editing_mode != vi_mode) { old = rl_kill_ring[slot]; new = (char *)xmalloc (1 + strlen (old) + strlen (text)); diff --git a/lib/readline/misc.c b/lib/readline/misc.c index d50a4c3a..716586c7 100644 --- a/lib/readline/misc.c +++ b/lib/readline/misc.c @@ -578,7 +578,7 @@ rl_get_previous_history (int count, int key) if (count < 0) return (rl_get_next_history (-count, key)); - if (count == 0) + if (count == 0 || history_list () == 0) return 0; /* either not saved by rl_newline or at end of line, so set appropriately. */ @@ -608,7 +608,10 @@ rl_get_previous_history (int count, int key) temp = old_temp; if (temp == 0) - rl_ding (); + { + rl_maybe_unsave_line (); + rl_ding (); + } else { rl_replace_from_history (temp, 0); diff --git a/parse.y b/parse.y index 1c23bc06..7ca4a64e 100644 --- a/parse.y +++ b/parse.y @@ -823,25 +823,25 @@ for_command: FOR WORD newline_list DO compound_list DONE arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE { $$ = make_arith_for_command ($2, $6, arith_for_lineno); - /* if ($$ == 0) YYERROR; */ + if ($$ == 0) YYERROR; if (word_top > 0) word_top--; } | FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}' { $$ = make_arith_for_command ($2, $6, arith_for_lineno); - /* if ($$ == 0) YYERROR; */ + if ($$ == 0) YYERROR; if (word_top > 0) word_top--; } | FOR ARITH_FOR_EXPRS DO compound_list DONE { $$ = make_arith_for_command ($2, $4, arith_for_lineno); - /* if ($$ == 0) YYERROR; */ + if ($$ == 0) YYERROR; if (word_top > 0) word_top--; } | FOR ARITH_FOR_EXPRS '{' compound_list '}' { $$ = make_arith_for_command ($2, $4, arith_for_lineno); - /* if ($$ == 0) YYERROR; */ + if ($$ == 0) YYERROR; if (word_top > 0) word_top--; } ; @@ -5217,6 +5217,11 @@ got_token: /*itrace("read_token_word: returning REDIR_WORD for %s", the_word->word);*/ return (REDIR_WORD); } + else + /* valid_array_reference can call the parser recursively; need to + make sure that yylval.word doesn't change if we are going to + return WORD or ASSIGNMENT_WORD */ + yylval.word = the_word; } result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT)) diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 554f3d6e..58c375b7 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/arith-for.right b/tests/arith-for.right index 5b25c5eb..640a50d0 100644 --- a/tests/arith-for.right +++ b/tests/arith-for.right @@ -64,11 +64,11 @@ fx () 0 1 2 -./arith-for.tests: line 77: syntax error: arithmetic expression required -./arith-for.tests: line 77: syntax error: `(( i=0; "i < 3" ))' +/usr/local/build/chet/bash/bash-current/bash: -c: line 0: syntax error: arithmetic expression required +/usr/local/build/chet/bash/bash-current/bash: -c: line 0: syntax error: `(( i=0; "i < 3" ))' 2 -./arith-for.tests: line 83: syntax error: `;' unexpected -./arith-for.tests: line 83: syntax error: `(( i=0; i < 3; i++; 7 ))' +/usr/local/build/chet/bash/bash-current/bash: -c: line 0: syntax error: `;' unexpected +/usr/local/build/chet/bash/bash-current/bash: -c: line 0: syntax error: `(( i=0; i < 3; i++; 7 ))' 2 20 20 diff --git a/tests/arith-for.tests b/tests/arith-for.tests index 00e2d4ae..42b8aad8 100644 --- a/tests/arith-for.tests +++ b/tests/arith-for.tests @@ -74,16 +74,16 @@ type fx fx # errors -for (( i=0; "i < 3" )) +${THIS_SH} -c 'for (( i=0; "i < 3" )) do echo $i -done +done' echo $? -for (( i=0; i < 3; i++; 7 )) +${THIS_SH} -c 'for (( i=0; i < 3; i++; 7 )) do echo $i -done +done' echo $? # one-liners added in post-bash-2.04 diff --git a/tests/comsub.tests b/tests/comsub.tests index fceea00f..dbae1e3a 100644 --- a/tests/comsub.tests +++ b/tests/comsub.tests @@ -45,7 +45,7 @@ bar') echo ${foo:-$(echo a{b,c})} >/dev/null # parsing problem based on recursively calling bison parser through bash-4.4 -for (( INDEX=0; INDEX<$((10-$(expr length $V_NAME))); INDEX++ )) +for (( INDEX=0; INDEX<$((10-$(echo length $V_NAME))); INDEX++ )) do : done