From 4be5608573b2be2e31f3d2a01446e22e1c9d7839 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 27 Jan 2021 11:49:50 -0500 Subject: [PATCH] commit bash-20210122 snapshot --- CWRU/CWRU.chlog | 31 ++++++++++++ lib/glob/glob.c | 103 ++++++++++++++++++++++++++++------------ lib/readline/callback.c | 3 +- lib/readline/signals.c | 2 + subst.c | 21 +++++--- tests/RUN-ONE-TEST | 2 +- tests/errors.right | 2 +- 7 files changed, 124 insertions(+), 40 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 456b5477..145d6541 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9419,3 +9419,34 @@ lib/readline/{rlprivate.h,{isearch,search,undo}.c} remove extern declaration from c source files, using HS_HISTORY_VERSION in the same way + 1/24 + ---- +lib/readline/signals.c + - _rl_handle_signal: make sure that all sigprocmask calls are protected + by HAVE_POSIX_SIGNALS. Report and fix from Tom Tromey + + 1/26 + ---- +lib/readline/callback.c + - rl_callback_read_char: make sure rl_linefunc is non-NULL before + calling through the pointer. The line function could have been + removed by the application before readline processes any typeahead + input. Bug reported by Matthias Klose , pointer + to root cause from Koichi Murase + +lib/glob/glob.c + - skipname,wskipname: put in some additional checks for `.' to ensure + that we don't get false positives (or incomplete tests) that can + affect the results of extglob patterns. Reported by + gregrwm + + 1/27 + ---- +lib/glob/glob.c + - extglob_skipname,wextglob_skipname: fixed an off-by-one error (SE + was being set to one character before the end of the pattern string, + not the null character at the end of the pattern string like other + callers of glob_patscan) that caused the last character of the last + subpattern to be cut off when calling skipname + - extglob_skipname,wextglob_skipname: some cleanups so the code is + closer to identical for the single-byte and wide character versions diff --git a/lib/glob/glob.c b/lib/glob/glob.c index eb6277f0..8d1f426b 100644 --- a/lib/glob/glob.c +++ b/lib/glob/glob.c @@ -185,6 +185,13 @@ glob_pattern_p (pattern) } #if EXTENDED_GLOB + +#if defined (HANDLE_MULTIBYTE) +# define XSKIPNAME(p, d, f) mbskipname(p, d, f) +#else +# define XSKIPNAME(p, d, f) skipname(p, d, f) +#endif + /* Return 1 if all subpatterns in the extended globbing pattern PAT indicate that the name should be skipped. XXX - doesn't handle pattern negation, not sure if it should */ @@ -199,25 +206,20 @@ extglob_skipname (pat, dname, flags) negate = *pat == '!'; wild = *pat == '*' || *pat == '?'; pp = pat + 2; - se = pp + strlen (pp) - 1; /* end of string */ - pe = glob_patscan (pp, se, 0); /* end of extglob pattern (( */ - /* we should check for invalid extglob pattern here */ + se = pp + strlen (pp); /* end of pattern string */ + pe = glob_patscan (pp, se, 0); /* end of extglob pattern */ + + /* if pe == 0, this is an invalid extglob pattern */ if (pe == 0) return 0; /* if pe != se we have more of the pattern at the end of the extglob pattern. Check the easy case first ( */ - if (pe == se && *pe == ')' && (t = strchr (pp, '|')) == 0) + if (pe == se && *pe == 0 && pe[-1] == ')' && (t = strchr (pp, '|')) == 0) { - *pe = '\0'; -#if defined (HANDLE_MULTIBYTE) - r = mbskipname (pp, dname, flags); -#else - r = skipname (pp, dname, flags); /*(*/ -#endif - *pe = ')'; - if (wild && pe[1]) /* if we can match zero instances, check further */ - return (skipname (pe+1, dname, flags)); + pe[-1] = '\0'; + r = XSKIPNAME (pp, dname, flags); /*(*/ + pe[-1] = ')'; return r; } @@ -229,21 +231,21 @@ extglob_skipname (pat, dname, flags) /* check every subpattern */ while (t = glob_patscan (pp, pe, '|')) { + /* If T == PE and *T == 0 (&& PE[-1] == RPAREN), we have hit the end + of a pattern with no trailing characters. */ n = t[-1]; /* ( */ - if (extglob_pattern_p (pp) && n == ')') + if (extglob_pattern_p (pp) && n == ')') /* nested extglob? */ t[-1] = n; /* no-op for now */ else t[-1] = '\0'; -#if defined (HANDLE_MULTIBYTE) - r = mbskipname (pp, dname, flags); -#else - r = skipname (pp, dname, flags); -#endif + r = XSKIPNAME (pp, dname, flags); t[-1] = n; if (r == 0) /* if any pattern says not skip, we don't skip */ return r; pp = t; - } /*(*/ + if (pp == pe) + break; + } /* glob_patscan might find end of string */ if (pp == se) @@ -251,7 +253,8 @@ extglob_skipname (pat, dname, flags) /* but if it doesn't then we didn't match a leading dot */ if (wild && *pe) /* if we can match zero instances, check further */ - return (skipname (pe, dname, flags)); + return (XSKIPNAME (pe, dname, flags)); + return 1; } #endif @@ -264,6 +267,8 @@ skipname (pat, dname, flags) char *dname; int flags; { + int i; + #if EXTENDED_GLOB if (extglob_pattern_p (pat)) /* XXX */ return (extglob_skipname (pat, dname, flags)); @@ -284,6 +289,20 @@ skipname (pat, dname, flags) (pat[0] != '\\' || pat[1] != '.')) return 1; + /* Special checks for `.'. The only things that can match `.' are ".", + "\.", ".*", and "\.*". We don't try to match everything here, just + make sure that we don't let something obviously disqualifying by. */ + else if (dname[0] == '.' && dname[1] == '\0') + { + if (pat[0] != '.' && (pat[0] != '\\' || pat[1] != '.')) + return 1; + i = (pat[0] == '.') ? 1 : 2; + if (pat[i] && pat[i] != '*') + return 1; + } + + /* We don't currently have any additional special checks for `..' */ + return 0; } @@ -294,6 +313,8 @@ wskipname (pat, dname, flags) wchar_t *pat, *dname; int flags; { + int i; + if (glob_always_skip_dot_and_dotdot && WDOT_OR_DOTDOT (dname)) return 1; @@ -306,11 +327,23 @@ wskipname (pat, dname, flags) /* If a leading dot must be explicitly matched, check to see if the pattern and dirname both have one. */ - else if (noglob_dot_filenames && dname[0] == L'.' && + else if (noglob_dot_filenames && dname[0] == L'.' && pat[0] != L'.' && (pat[0] != L'\\' || pat[1] != L'.')) return 1; + /* Special checks for `.'. The only things that can match `.' are ".", + "\.", ".*", and "\.*". We don't try to match everything here, just + make sure that we don't let something obviously disqualifying by. */ + else if (dname[0] == L'.' && dname[1] == L'\0') + { + if (pat[0] != L'.' && (pat[0] != L'\\' || pat[1] != L'.')) + return 1; + i = (pat[0] == L'.') ? 1 : 2; + if (pat[i] != L'\0' && pat[i] != L'*') + return 1; + } + return 0; } @@ -320,22 +353,26 @@ wextglob_skipname (pat, dname, flags) int flags; { #if EXTENDED_GLOB - wchar_t *pp, *pe, *t, n, *se; + wchar_t *pp, *pe, *t, *se, n; int r, negate, wild, nullpat; negate = *pat == L'!'; wild = *pat == L'*' || *pat == L'?'; pp = pat + 2; - se = pp + wcslen (pp) - 1; /*(*/ + se = pp + wcslen (pp); pe = glob_patscan_wc (pp, se, 0); - if (pe == se && *pe == ')' && (t = wcschr (pp, L'|')) == 0) + /* if pe == 0, this is an invalid extglob pattern */ + if (pe == 0) + return 0; + + /* if pe != se we have more of the pattern at the end of the extglob + pattern. Check the easy case first ( */ + if (pe == se && *pe == L'\0' && pe[-1] == L')' && (t = wcschr (pp, L'|')) == 0) { - *pe = L'\0'; + pe[-1] = L'\0'; r = wskipname (pp, dname, flags); /*(*/ - *pe = L')'; - if (wild && pe[1] != L'\0') - return (wskipname (pe+1, dname, flags)); + pe[-1] = L')'; return r; } @@ -348,7 +385,7 @@ wextglob_skipname (pat, dname, flags) while (t = glob_patscan_wc (pp, pe, '|')) { n = t[-1]; /* ( */ - if (wextglob_pattern_p (pp) && n == L')') + if (wextglob_pattern_p (pp) && n == L')') /* nested extglob? */ t[-1] = n; /* no-op for now */ else t[-1] = L'\0'; @@ -357,14 +394,18 @@ wextglob_skipname (pat, dname, flags) if (r == 0) return 0; pp = t; + if (pp == pe) + break; } - if (pp == pe) /* glob_patscan_wc might find end of pattern */ + /* glob_patscan_wc might find end of string */ + if (pp == se) return r; /* but if it doesn't then we didn't match a leading dot */ if (wild && *pe != L'\0') return (wskipname (pe, dname, flags)); + return 1; #else return (wskipname (pat, dname, flags)); diff --git a/lib/readline/callback.c b/lib/readline/callback.c index a466cf9b..66e8d113 100644 --- a/lib/readline/callback.c +++ b/lib/readline/callback.c @@ -278,7 +278,8 @@ rl_callback_read_char (void) rl_clear_signals (); #endif in_handler = 0; - (*rl_linefunc) (line); + if (rl_linefunc) /* just in case */ + (*rl_linefunc) (line); /* If the user did not clear out the line, do it for him. */ if (rl_line_buffer[0]) diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 0943c643..ecaf699e 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -266,8 +266,10 @@ _rl_handle_signal (int sig) case SIGQUIT: #endif +#if defined (HAVE_POSIX_SIGNALS) if (block_sig) sigprocmask (SIG_BLOCK, &set, &oset); +#endif rl_echo_signal_char (sig); rl_cleanup_after_signal (); diff --git a/subst.c b/subst.c index d7b5a6b6..03af0534 100644 --- a/subst.c +++ b/subst.c @@ -8197,19 +8197,28 @@ parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags) /* */ /****************************************************************/ -#ifdef INCLUDE_UNUSED +#if 0 /* TAG: bash-5.2? */ static int shouldexp_replacement (s) char *s; { - register char *p; + size_t slen; + int sindex, c; + DECLARE_MBSTATE; - for (p = s; p && *p; p++) + sindex = 0; + slen = STRLEN (s); + while (c = s[sindex]) { - if (*p == '\\') - p++; - else if (*p == '&') + if (c == '\\') + { + sindex++; + if (s[sindex] == 0) + return 0; + } + else if (c == '&') return 1; + ADVANCE_CHAR (s, slen, sindex); } return 0; } diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 0b063810..c8bef8dd 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/errors.right b/tests/errors.right index 93c73a39..0bfe7418 100644 --- a/tests/errors.right +++ b/tests/errors.right @@ -16,7 +16,7 @@ unset: usage: unset [-f] [-v] [-n] [name ...] ./errors.tests: line 67: unset: XPATH: cannot unset: readonly variable ./errors.tests: line 73: unset: cannot simultaneously unset a function and a variable ./errors.tests: line 76: declare: -z: invalid option -declare: usage: declare [-aAfFgiIlnrtux] [-p] [name[=value] ...] +declare: usage: declare [-aAfFgiIlnrtux] [name[=value] ...] or declare -p [-aAfFilnrtux] [name ...] ./errors.tests: line 78: declare: `-z': not a valid identifier ./errors.tests: line 79: declare: `/bin/sh': not a valid identifier ./errors.tests: line 83: declare: cannot use `-f' to make functions