From 589afb3c12a8ceac97a329faad027d760cb29617 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Fri, 22 Apr 2016 11:34:34 -0400 Subject: [PATCH] commit bash-20160408 snapshot --- CWRU/CWRU.chlog | 31 +++++++++++++++++++++++++++++++ MANIFEST | 4 +++- arrayfunc.c | 5 +---- builtins/alias.def | 1 + builtins/complete.def | 1 + builtins/jobs.def | 1 + doc/bash.1 | 2 +- lib/glob/sm_loop.c | 24 ++++++++++++++++++------ shell.c | 36 ++++++++++++++++++++++++++++-------- tests/alias2.sub | 2 +- tests/exportfunc.tests | 4 ++-- tests/extglob.right | 5 +++++ tests/extglob.tests | 2 ++ tests/extglob4.sub | 22 ++++++++++++++++++++++ tests/heredoc.right | 12 ++++++------ tests/heredoc3.sub | 3 +++ tests/history.tests | 2 +- tests/history1.sub | 2 +- 18 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 tests/extglob4.sub diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 6b9900f3..a9bdb915 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -10601,3 +10601,34 @@ parse.y reserved words; set lex_rwlen to 0 so we know to start reading a new one + 4/7 + --- +builtins/{alias,complete,jobs}.def + - {alias,compopt,disown}: add missing `CASE_HELPOPT;' so --help option + prints help longdoc instead of builtin_usage() + + 4/8 + --- +arrayfunc.c + - assign_array_var_from_word_list: use bind_array_var_internal instead + of inline code, so value conversions happen on assignment (case + modification, arithmetic evaluation, etc). Fixes bug reported by + Geir Hauge + + 4/9 + --- +shell.c + - main: change the logic that determines whether or not bash is running + under an emacs terminal emulator so it works with future versions of + emacs, which will change to use only $INSIDE_EMACS. Report and fix + from Paul Eggert + +lib/glob/sm_loop.c + - EXT: if we see ?(pat), we can match 0 or 1 times, so if we don't + match, we should consume the extglob pattern and go on to attempt + to match the rest of the pattern against the string. Fixes bug + reported by Isabella Parakiss + - GMATCH: in case `*', don't short-circuit and match anything if the + * is the last character in the pattern until after we check the + special cases for matching a `.'. Fixes bugs reported back on 3/23 + by Isabella Parakiss diff --git a/MANIFEST b/MANIFEST index 9a5cc979..c7fc63f1 100644 --- a/MANIFEST +++ b/MANIFEST @@ -984,11 +984,13 @@ tests/extglob.tests f tests/extglob.right f tests/extglob1.sub f tests/extglob1a.sub f -tests/extglob3.sub f +tests/extglob2.sub f tests/extglob2.tests f tests/extglob2.right f +tests/extglob3.sub f tests/extglob3.tests f tests/extglob3.right f +tests/extglob4.sub f tests/func.tests f tests/func.right f tests/func1.sub f diff --git a/arrayfunc.c b/arrayfunc.c index c5a80bad..9e83864f 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -403,10 +403,7 @@ assign_array_var_from_word_list (var, list, flags) i = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0; for (l = list; l; l = l->next, i++) - if (var->assign_func) - (*var->assign_func) (var, l->word->word, i, 0); - else - array_insert (a, i, l->word->word); + bind_array_var_internal (var, i, 0, l->word->word, flags & ~ASS_APPEND); VUNSETATTR (var, att_invisible); /* no longer invisible */ diff --git a/builtins/alias.def b/builtins/alias.def index c598fe74..50800247 100644 --- a/builtins/alias.def +++ b/builtins/alias.def @@ -87,6 +87,7 @@ alias_builtin (list) pflag = 1; dflags |= AL_REUSABLE; break; + CASE_HELPOPT; default: builtin_usage (); return (EX_USAGE); diff --git a/builtins/complete.def b/builtins/complete.def index a0329ff6..6bdf88b4 100644 --- a/builtins/complete.def +++ b/builtins/complete.def @@ -813,6 +813,7 @@ compopt_builtin (list) case 'E': Eflag = 1; break; + CASE_HELPOPT; default: builtin_usage (); return (EX_USAGE); diff --git a/builtins/jobs.def b/builtins/jobs.def index 2dde2552..be1a7d8f 100644 --- a/builtins/jobs.def +++ b/builtins/jobs.def @@ -253,6 +253,7 @@ disown_builtin (list) case 'r': running_jobs = 1; break; + CASE_HELPOPT; default: builtin_usage (); return (EX_USAGE); diff --git a/doc/bash.1 b/doc/bash.1 index f848db46..829a4a55 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -628,7 +628,7 @@ are executed sequentially; the shell waits for each command to terminate in turn. The return status is the exit status of the last command executed. .PP -AND and OR lists are sequences of one of more pipelines separated by the +AND and OR lists are sequences of one or more pipelines separated by the \fB&&\fP and \fB||\fP control operators, respectively. AND and OR lists are executed with left associativity. An AND list has the form diff --git a/lib/glob/sm_loop.c b/lib/glob/sm_loop.c index 9e16412c..c3a2aa37 100644 --- a/lib/glob/sm_loop.c +++ b/lib/glob/sm_loop.c @@ -119,9 +119,6 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); break; case '*': /* Match zero or more characters */ - if (p == pe) - return 0; - if ((flags & FNM_PERIOD) && sc == L('.') && (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/')))) /* `*' cannot match a `.' if it is the first character of the @@ -129,6 +126,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); we are matching a pathname. */ return FNM_NOMATCH; + if (p == pe) + return 0; + /* Collapse multiple consecutive `*' and `?', but make sure that one character of the string is consumed for each `?'. */ for (c = *p++; (c == L('?') || c == L('*')); c = *p++) @@ -140,14 +140,26 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); else if ((flags & FNM_EXTMATCH) && c == L('?') && *p == L('(')) /* ) */ { CHAR *newn; + +#if 0 for (newn = n; newn < se; ++newn) { if (EXTMATCH (c, newn, se, p, pe, flags) == 0) return (0); } - /* We didn't match. If we have a `?(...)', we can match 0 - or 1 times. */ - return 0; +#else + /* We can match 0 or 1 times. If we match, return success */ + if (EXTMATCH (c, n, se, p, pe, flags) == 0) + return (0); +#endif + + /* We didn't match the extended glob pattern, but + that's OK, since we can match 0 or 1 occurrences. + We need to skip the glob pattern and see if we + match the rest of the string. */ + newn = PATSCAN (p + 1, pe, 0); + /* If NEWN is 0, we have an ill-formed pattern. */ + p = newn ? newn : pe; } #endif else if (c == L('?')) diff --git a/shell.c b/shell.c index c9549a3a..0c83f63e 100644 --- a/shell.c +++ b/shell.c @@ -573,25 +573,45 @@ main (argc, argv, env) set_default_locale_vars (); /* - * M-x term -> TERM=eterm EMACS=22.1 (term:0.96) (eterm) - * M-x shell -> TERM=dumb EMACS=t (no line editing) - * M-x terminal -> TERM=emacs-em7955 EMACS= (line editing) + * M-x term -> TERM=eterm-color INSIDE_EMACS='251,term:0.96' (eterm) + * M-x shell -> TERM='dumb' INSIDE_EMACS='25.1,comint' (no line editing) + * + * Older versions of Emacs may set EMACS to 't' or to something like + * '22.1 (term:0.96)' instead of (or in addition to) setting INSIDE_EMACS. + * They may set TERM to 'eterm' instead of 'eterm-color'. They may have + * a now-obsolete command that sets neither EMACS nor INSIDE_EMACS: + * M-x terminal -> TERM='emacs-em7955' (line editing) */ if (interactive_shell) { - char *term, *emacs; + char *term, *emacs, *inside_emacs;; + int emacs_term, in_emacs; term = get_string_value ("TERM"); emacs = get_string_value ("EMACS"); + inside_emacs = get_string_value ("INSIDE_EMACS"); + + if (inside_emacs) + { + emacs_term = strstr (inside_emacs, ",term:") != 0; + in_emacs = 1; + } + else if (emacs) + { + /* Infer whether we are in an older Emacs. */ + emacs_term = strstr (emacs, " (term:") != 0; + in_emacs = emacs_term || STREQ (emacs, "t"); + } + else + in_emacs = emacs_term = 0; /* Not sure any emacs terminal emulator sets TERM=emacs any more */ no_line_editing |= STREQ (term, "emacs"); - no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0' && STREQ (term, "dumb"); - no_line_editing |= get_string_value ("INSIDE_EMACS") != 0; + no_line_editing |= in_emacs && STREQ (term, "dumb"); /* running_under_emacs == 2 for `eterm' */ - running_under_emacs = (emacs != 0) || STREQN (term, "emacs", 5); - running_under_emacs += STREQN (term, "eterm", 5) && emacs && strstr (emacs, "term"); + running_under_emacs = in_emacs || STREQN (term, "emacs", 5); + running_under_emacs += emacs_term && STREQN (term, "eterm", 5); if (running_under_emacs) gnu_error_format = 1; diff --git a/tests/alias2.sub b/tests/alias2.sub index e72a380b..76044485 100644 --- a/tests/alias2.sub +++ b/tests/alias2.sub @@ -1,5 +1,5 @@ THIS=alias2 -FN=$THIS.script +FN=$TMPDIR/$THIS.script cat > $FN <<'EOF' # diff --git a/tests/exportfunc.tests b/tests/exportfunc.tests index c2e17427..f5ef54f0 100644 --- a/tests/exportfunc.tests +++ b/tests/exportfunc.tests @@ -24,11 +24,11 @@ env -i BASH_FUNC_X%%='() { (a)=>\' ${THIS_SH} -c cve7169-bad 2>/dev/null : < cve7169-bad rm -f cve7169-bad -echo cve7169-bad2 > bar +echo cve7169-bad2 > $TMPDIR/bar rm -f cve7169-bad2 eval 'X() { (a)>\' ; . ./bar 2>/dev/null : < cve7169-bad2 -rm -f cve7169-bad2 bar +rm -f cve7169-bad2 $TMPDIR/bar # CVE-2014-7186 ${THIS_SH} ./exportfunc1.sub diff --git a/tests/extglob.right b/tests/extglob.right index 84a52252..efb7e5fb 100644 --- a/tests/extglob.right +++ b/tests/extglob.right @@ -100,3 +100,8 @@ a.log a.log . .. a.log +.x .y .z +a b c +.x .y .z a b c +a b c +a b c diff --git a/tests/extglob.tests b/tests/extglob.tests index ac1df77a..a51c4db1 100644 --- a/tests/extglob.tests +++ b/tests/extglob.tests @@ -372,4 +372,6 @@ ${THIS_SH} ./extglob1a.sub ${THIS_SH} ./extglob3.sub +${THIS_SH} ./extglob4.sub + exit 0 diff --git a/tests/extglob4.sub b/tests/extglob4.sub new file mode 100644 index 00000000..b76869b7 --- /dev/null +++ b/tests/extglob4.sub @@ -0,0 +1,22 @@ +: ${TMPDIR:=/tmp} +GTDIR=$TMPDIR/extglob4-$$ + +shopt -s extglob +[ -d "${GTDIR}" ] || mkdir "${GTDIR}" +cd "${GTDIR}" || { + echo "extglob4: cannot cd to ${GTDIR}" + exit 2 +} + +touch a b c .x .y .z +echo .!(|.) # correct +echo * # correct + +echo @(*|.!(|.)) # wrong, adds . and .. +echo @(*|@(f)) # ?? +echo @(*|@(ff)) + +cd / +rm -rf $GTDIR + +[[ a = a*?(/)b ]] && echo bad match 1 diff --git a/tests/heredoc.right b/tests/heredoc.right index 8df91c5c..137a2956 100644 --- a/tests/heredoc.right +++ b/tests/heredoc.right @@ -59,13 +59,13 @@ qux bar qux abc def geh -./heredoc3.sub: line 6: warning: here-document at line 4 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 9: warning: here-document at line 7 delimited by end-of-file (wanted `EOF') = here is the text = -./heredoc3.sub: line 12: warning: here-document at line 10 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 15: warning: here-document at line 13 delimited by end-of-file (wanted `EOF') this paren ) is not a problem -./heredoc3.sub: line 18: warning: here-document at line 16 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 21: warning: here-document at line 19 delimited by end-of-file (wanted `EOF') these balanced parens ( ) are not a problem -./heredoc3.sub: line 24: warning: here-document at line 22 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 27: warning: here-document at line 25 delimited by end-of-file (wanted `EOF') quoted balanced parens \( ) are not a problem either more text in a subshell some more text in a different subshell @@ -82,8 +82,8 @@ end helloEND hello \END end hello\END -./heredoc3.sub: line 75: warning: here-document at line 73 delimited by end-of-file (wanted `EOF') -./heredoc3.sub: line 76: syntax error: unexpected end of file +./heredoc3.sub: line 78: warning: here-document at line 76 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 79: syntax error: unexpected end of file comsub here-string ./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF') hi diff --git a/tests/heredoc3.sub b/tests/heredoc3.sub index 9d3d8467..baf91c14 100644 --- a/tests/heredoc3.sub +++ b/tests/heredoc3.sub @@ -1,3 +1,6 @@ +SAVEPWD=$PWD +cd $TMPDIR || echo "heredoc3.sub: cannot cd to $TMPDIR" >&2 + text=$(cat <