From e51c9c17af51e4055efb5a2cc36739d1d7ae457f Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 29 Jan 2017 08:30:14 -0800 Subject: 40453: signal handler safety for callers of patcompile(PAT_STATIC), which is not re-entrant. --- Src/Zle/compctl.c | 32 +++++++++++++++++++++++++------- Src/Zle/complete.c | 10 ++++++++++ Src/Zle/computil.c | 8 ++++++++ Src/Zle/zle_hist.c | 10 ++++++---- 4 files changed, 49 insertions(+), 11 deletions(-) (limited to 'Src/Zle') diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 52c6f1233..9e6ccb404 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -99,7 +99,7 @@ freecompctlp(HashNode hn) } /**/ -void +static void freecompctl(Compctl cc) { if (cc == &cc_default || @@ -142,7 +142,7 @@ freecompctl(Compctl cc) } /**/ -void +static void freecompcond(void *a) { Compcond cc = (Compcond) a; @@ -186,7 +186,7 @@ freecompcond(void *a) } /**/ -int +static int compctlread(char *name, char **args, Options ops, char *reply) { char *buf, *bptr; @@ -1564,6 +1564,8 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) Compctl cc = NULL; int ret = 0; + queue_signals(); + /* clear static flags */ cclist = 0; showmask = 0; @@ -1571,12 +1573,15 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) /* Parse all the arguments */ if (*argv) { /* Let's see if this is a global matcher definition. */ - if ((ret = get_gmatcher(name, argv))) + if ((ret = get_gmatcher(name, argv))) { + unqueue_signals(); return ret - 1; + } cc = (Compctl) zshcalloc(sizeof(*cc)); if (get_compctl(name, &argv, cc, 1, 0, 0)) { freecompctl(cc); + unqueue_signals(); return 1; } @@ -1604,6 +1609,7 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) printcompctl((cclist & COMP_LIST) ? "" : "DEFAULT", &cc_default, 0, 0); printcompctl((cclist & COMP_LIST) ? "" : "FIRST", &cc_first, 0, 0); print_gmatcher((cclist & COMP_LIST)); + unqueue_signals(); return ret; } @@ -1642,6 +1648,7 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) printcompctl("", &cc_first, 0, 0); if (cclist & COMP_LISTMATCH) print_gmatcher(COMP_LIST); + unqueue_signals(); return ret; } @@ -1656,6 +1663,7 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) compctl_process_cc(argv, cc); } + unqueue_signals(); return ret; } @@ -1667,12 +1675,18 @@ bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) static int bin_compcall(char *name, UNUSED(char **argv), Options ops, UNUSED(int func)) { + int ret; + if (incompfunc != 1) { zwarnnam(name, "can only be called from completion function"); return 1; } - return makecomplistctl((OPT_ISSET(ops,'T') ? 0 : CFN_FIRST) | - (OPT_ISSET(ops,'D') ? 0 : CFN_DEFAULT)); + + queue_signals(); + ret = makecomplistctl((OPT_ISSET(ops,'T') ? 0 : CFN_FIRST) | + (OPT_ISSET(ops,'D') ? 0 : CFN_DEFAULT)); + unqueue_signals(); + return ret; } /* @@ -1756,6 +1770,8 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) int onm = nmatches, odm = diffmatches, osi = movefd(0); LinkNode n; + queue_signals(); + /* We build a copy of the list of matchers to use to make sure that this * works even if a shell function called from the completion code changes * the global matchers. */ @@ -1883,6 +1899,8 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) } redup(osi, 0); dat->lst = 1; + + unqueue_signals(); return 0; } @@ -2044,7 +2062,7 @@ maketildelist(void) /* This does the check for compctl -x `n' and `N' patterns. */ /**/ -int +static int getcpat(char *str, int cpatindex, char *cpat, int class) { char *s, *t, *p; diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index 48fcd4751..49b338f29 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -896,6 +896,8 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1; Patprog pp; + queue_signals(); /* Protect PAT_STATIC */ + i = compcurrent - 1; if (i < 0 || i >= l) return 0; @@ -930,6 +932,9 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) t = 0; if (t && mod) restrict_range(b, e); + + unqueue_signals(); + return t; } case CVT_PRENUM: @@ -952,6 +957,8 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) { Patprog pp; + queue_signals(); /* Protect PAT_STATIC */ + if (!na) return 0; @@ -1036,6 +1043,9 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) if (mod) ignore_suffix(ol - (p - compsuffix)); } + + unqueue_signals(); + return 1; } } diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 5b9ceec1a..325da6ddb 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -3928,6 +3928,8 @@ bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) if (*q) { char *qq, *qqq; + queue_signals(); + if (c) *c = '\0'; @@ -3999,6 +4001,8 @@ bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } if (c) *c = ':'; + + unqueue_signals(); } } if (num) { @@ -4708,6 +4712,8 @@ cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, if (!*p) continue; + queue_signals(); /* Protect PAT_STATIC */ + tokenize(f); pprog = patcompile(f, PAT_STATIC, NULL); untokenize(f); @@ -4740,6 +4746,8 @@ cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, } } } + + unqueue_signals(); } } } diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index 434735de9..581ca4979 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -1220,10 +1220,12 @@ doisearch(char **args, int dir, int pattern) char *patbuf = ztrdup(sbuf); char *patstring; /* - * Do not use static pattern buffer (PAT_STATIC) since we call zle hooks, - * which might call other pattern functions. Use PAT_ZDUP instead. - * Use PAT_NOANCH because we don't need the match - * anchored to the end, even if it is at the start. + * Do not use static pattern buffer (PAT_STATIC) since we + * call zle hooks, which might call other pattern + * functions. Use PAT_ZDUP because we re-use the pattern + * in subsequent loops, so we can't pushheap/popheap. + * Use PAT_NOANCH because we don't need the match anchored + * to the end, even if it is at the start. */ int patflags = PAT_ZDUP|PAT_NOANCH; if (sbuf[0] == '^') { -- cgit 1.4.1