From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14753 invoked by alias); 29 Jan 2017 02:55:11 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 40453 Received: (qmail 26717 invoked from network); 29 Jan 2017 02:55:10 -0000 X-Qmail-Scanner-Diagnostics: from mercury.zanshin.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(64.84.47.142):SA:0(0.0/5.0):. Processed in 3.644323 secs); 29 Jan 2017 02:55:10 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, SPF_PASS,T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: schaefer@ipost.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at ipost.com designates 64.84.47.142 as permitted sender) X-Return-Path: X-Received: from atilla.zanshin.com (atilla.zanshin.com [64.84.47.246]) by mercury.zanshin.com (8.13.1/8.13.1) with ESMTP id v0T014Uf010374 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sat, 28 Jan 2017 16:01:05 -0800 X-Resolve: OK X-Received: from mail-vk0-f65.google.com (mail-vk0-f65.google.com [209.85.213.65]) by atilla.zanshin.com (8.13.8/8.13.8) with ESMTP id v0T010Zs027728 for ; Sat, 28 Jan 2017 16:01:00 -0800 X-Received: by mail-vk0-f65.google.com with SMTP id 23so24030586vkc.2 for ; Sat, 28 Jan 2017 16:01:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brasslantern-com.20150623.gappssmtp.com; s=20150623; h=from:message-id:date:in-reply-to:comments:references:to:subject :mime-version; bh=fL0FQ3CO3k1hmuJJ15kI8/q4ipVsPN11sH8XzG3uE7A=; b=mfk7Zx9R0ogYK8pxKEbxwjMiKwiOf3xthrwYrGOhoMbWbH6slDl4u5y9DpzvbH5Ho2 LBGAhT8nYGFM46Sh2Ujwg1Q/sRzI9vLHdyy46Iz6W+GEw00IHnQsbPWA5nw0BeYGK6uF SOgA8VjKtY1G6I9YbjU5fhOaBTL26v/MuxQE3UcZH1djlC1egvTwBjyij2IEFfBqmTQL 6GKu6qlxEcf17fZV4Z2uxA6q8XQrl760AdGvmBgVz3ZnuCJoZu1zVvtwA+0Wd7sF8jaX xsf3wNTBI6n8C3tX4NuKxGLAXBPJVEfifLTA2IG+ukh5ErzbskynFUsxW/QH/I9wmkjs TQUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:date:in-reply-to:comments :references:to:subject:mime-version; bh=fL0FQ3CO3k1hmuJJ15kI8/q4ipVsPN11sH8XzG3uE7A=; b=Jki91XOet+RRJwjDGc2U8y3W0hjgBSIphSxK2MdGX4QcZbhcesGQZW96DD6KhDz6ep EsA0YO2Y3XUQTmbiyzUH0r3R5cG47LYVZf20fXOaDzdgsPin0KTmvLniM8TZAGDdwie1 +XDvbDJZtAgoiiKmwLlaaJJmQv3hpUxtuGrii5CqD8RgOWyjxSaulr0nljMnjtvnVwQX eLkHhp1Me46iJ5VlqxqdlkxdNd+gkJ3SLyNixbGIVQtkV39JBU4qZg1E2IRcH9J8pDX6 0xSCpwVVCgu8N++T8cKe8eiArV1dOJxUdjA1BI3FFpgppTiVxUHEXB/xJM5UrzlOzp+P qABA== X-Gm-Message-State: AIkVDXJj5WjWEa4j5iAr+F0qzcJJOiJoJW/PxKkbdO+q07liDhAcnw+K+ofqEWZ/Ia+ANA== X-Received: by 10.31.106.65 with SMTP id f62mr6135292vkc.159.1485648054376; Sat, 28 Jan 2017 16:00:54 -0800 (PST) X-Received: from torch.brasslantern.com (c-76-102-191-95.hsd1.ca.comcast.net. [76.102.191.95]) by smtp.gmail.com with ESMTPSA id 94sm3483745uak.15.2017.01.28.16.00.52 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 28 Jan 2017 16:00:53 -0800 (PST) X-Received: from torch.brasslantern.com (localhost.localdomain [127.0.0.1]) by torch.brasslantern.com (8.13.1/8.13.1) with ESMTP id v0T01d6c019217; Sat, 28 Jan 2017 16:01:39 -0800 X-Received: (from schaefer@localhost) by torch.brasslantern.com (8.13.1/8.13.1/Submit) id v0T01cuK019216; Sat, 28 Jan 2017 16:01:38 -0800 From: Bart Schaefer Message-Id: <170128160138.ZM19215@torch.brasslantern.com> Date: Sat, 28 Jan 2017 16:01:38 -0800 In-Reply-To: <20170128194717.00b4be7e@ntlworld.com> Comments: In reply to Peter Stephenson "Re: [PATCH] isearch: do not use PAT_STATIC since we call zle hooks" (Jan 28, 7:47pm) References: <20170106172541.GA14113@fujitsu.shahaf.local2> <170108113358.ZM9462@torch.brasslantern.com> <20170108194021.18fb2011@ntlworld.com> <20170128194717.00b4be7e@ntlworld.com> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: Re: [PATCH] isearch: do not use PAT_STATIC since we call zle hooks MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Scanned-By: MIMEDefang 2.70 on 64.84.47.246 X-Envelope-Sender: ReSent-Date: Sat, 28 Jan 2017 18:54:13 -0800 (PST) ReSent-From: Bart Schaefer ReSent-To: zsh-workers@zsh.org ReSent-Subject: Re: [PATCH] isearch: do not use PAT_STATIC since we call zle hooks ReSent-Message-ID: ReSent-User-Agent: Alpine 2.00 (LRH 1167 2008-08-23) On Jan 28, 7:47pm, Peter Stephenson wrote: } } But my gut feel is compctl only ever got to the point that it was doing } simple local stuff that finished quickly, and we're morally entitled to } assume that anything that isn't like that is using compsys. So I'd be } inclined to try what you suggest and just make sure a few simple builtin } completions with compctl work. OK, with that confirmed ... here's a largish patch. It's somewhat arbitrary whether to change the PAT_* flag or to apply signal queuing. For example the patch that started all this (40285) uses PAT_ZDUP, but it would be possible to allow the pattern to be placed on the heap every time instead. However this is in a loop, and the pattern may change multiple times which could lead to several patterns piling up on the heap before we finally finish the loop and clean up. So I elected not to leave that as it was, though I updated some comments. In other cases it was obvious that global state was being changed so it seemed better to add, or to widen the scope of, queue_signals(). diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index 0ef7539..2c87be1 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -544,7 +544,8 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch) p = dupstring(args[1]); tokenize(p); remnulargs(p); - if (!(prog = patcompile(p, PAT_STATIC, NULL))) { + /* Signals handlers might stomp PAT_STATIC */ + if (!(prog = patcompile(p, PAT_ZDUP, NULL))) { zwarnnam(nam, "bad pattern: %s", args[1]); return 1; } @@ -682,9 +683,14 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch) write_loop(1, buf, used); } - if (seen && (!prog || matchok || !mustmatch)) - return 0; - return cmd->fin + 1; + { + int ret = cmd->fin + 1; + if (seen && (!prog || matchok || !mustmatch)) + ret = 0; + if (prog) + freepatprog(prog); + return ret; + } } static int diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index d95c0c2..19a8306 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -510,25 +510,33 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) zwarnnam(nam, "too many arguments"); return 1; } + + queue_signals(); /* Protect PAT_STATIC */ + if (context) { tokenize(context); zstyle_contprog = patcompile(context, PAT_STATIC, NULL); - if (!zstyle_contprog) + if (!zstyle_contprog) { + unqueue_signals(); return 1; + } } else zstyle_contprog = NULL; if (stylename) { s = (Style)zstyletab->getnode2(zstyletab, stylename); - if (!s) + if (!s) { + unqueue_signals(); return 1; + } zstyletab->printnode(&s->node, list); } else { scanhashtable(zstyletab, 1, 0, 0, zstyletab->printnode, list); } + unqueue_signals(); return 0; } switch (args[0][1]) { @@ -675,14 +683,20 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) char **vals; Patprog prog; + queue_signals(); /* Protect PAT_STATIC */ + tokenize(args[3]); if ((vals = lookupstyle(args[1], args[2])) && (prog = patcompile(args[3], PAT_STATIC, NULL))) { while (*vals) - if (pattry(prog, *vals++)) + if (pattry(prog, *vals++)) { + unqueue_signals(); return 0; + } } + + unqueue_signals(); return 1; } break; diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 52c6f12..9e6ccb4 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 48fcd47..49b338f 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 5b9ceec..325da6d 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 434735d..581ca49 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] == '^') { diff --git a/Src/builtin.c b/Src/builtin.c index 219fbc9..394d206 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -539,18 +539,18 @@ bin_enable(char *name, char **argv, Options ops, int func) /* With -m option, treat arguments as glob patterns. */ if (OPT_ISSET(ops,'m')) { for (; *argv; argv++) { + queue_signals(); + /* parse pattern */ tokenize(*argv); - if ((pprog = patcompile(*argv, PAT_STATIC, 0))) { - queue_signals(); + if ((pprog = patcompile(*argv, PAT_STATIC, 0))) match += scanmatchtable(ht, pprog, 0, 0, 0, scanfunc, 0); - unqueue_signals(); - } else { untokenize(*argv); zwarnnam(name, "bad pattern : %s", *argv); returnval = 1; } + unqueue_signals(); } /* If we didn't match anything, we return 1. */ if (!match) @@ -3136,9 +3136,9 @@ bin_functions(char *name, char **argv, Options ops, int func) } else if (OPT_ISSET(ops,'m')) { /* List matching functions. */ for (; *argv; argv++) { + queue_signals(); tokenize(*argv); if ((pprog = patcompile(*argv, PAT_STATIC, 0))) { - queue_signals(); for (p = mathfuncs, q = NULL; p; q = p) { MathFunc next; do { @@ -3157,12 +3157,12 @@ bin_functions(char *name, char **argv, Options ops, int func) if (p) p = p->next; } - unqueue_signals(); } else { untokenize(*argv); zwarnnam(name, "bad pattern : %s", *argv); returnval = 1; } + unqueue_signals(); } } else if (OPT_PLUS(ops,'M')) { /* Delete functions. -m is allowed but is handled above. */ @@ -3312,11 +3312,11 @@ bin_functions(char *name, char **argv, Options ops, int func) if (OPT_ISSET(ops,'m')) { on &= ~PM_UNDEFINED; for (; *argv; argv++) { + queue_signals(); /* expand argument */ tokenize(*argv); if ((pprog = patcompile(*argv, PAT_STATIC, 0))) { /* with no options, just print all functions matching the glob pattern */ - queue_signals(); if (!(on|off) && !OPT_ISSET(ops,'X')) { scanmatchshfunc(pprog, 1, 0, DISABLED, shfunctab->printnode, pflags, expand); @@ -3336,12 +3336,12 @@ bin_functions(char *name, char **argv, Options ops, int func) } } } - unqueue_signals(); } else { untokenize(*argv); zwarnnam(name, "bad pattern : %s", *argv); returnval = 1; } + unqueue_signals(); } return returnval; } @@ -3469,11 +3469,11 @@ bin_unset(char *name, char **argv, Options ops, int func) /* with -m option, treat arguments as glob patterns */ if (OPT_ISSET(ops,'m')) { while ((s = *argv++)) { + queue_signals(); /* expand */ tokenize(s); if ((pprog = patcompile(s, PAT_STATIC, NULL))) { /* Go through the parameter table, and unset any matches */ - queue_signals(); for (i = 0; i < paramtab->hsize; i++) { for (pm = (Param) paramtab->nodes[i]; pm; pm = next) { /* record pointer to next, since we may free this one */ @@ -3486,12 +3486,12 @@ bin_unset(char *name, char **argv, Options ops, int func) } } } - unqueue_signals(); } else { untokenize(s); zwarnnam(name, "bad pattern : %s", s); returnval = 1; } + unqueue_signals(); } /* If we didn't match anything, we return 1. */ if (!match) @@ -3655,6 +3655,7 @@ bin_whence(char *nam, char **argv, Options ops, int func) pushheap(); matchednodes = newlinklist(); } + queue_signals(); for (; *argv; argv++) { /* parse the pattern */ tokenize(*argv); @@ -3664,7 +3665,6 @@ bin_whence(char *nam, char **argv, Options ops, int func) returnval = 1; continue; } - queue_signals(); if (!OPT_ISSET(ops,'p')) { /* -p option is for path search only. * * We're not using it, so search for ... */ @@ -3695,9 +3695,9 @@ bin_whence(char *nam, char **argv, Options ops, int func) scanmatchtable(cmdnamtab, pprog, 1, 0, 0, (all ? fetchcmdnamnode : cmdnamtab->printnode), printflags); - - unqueue_signals(); + run_queued_signals(); } + unqueue_signals(); if (all) { allmatched = argv = zlinklist2array(matchednodes); matchednodes = NULL; @@ -4024,11 +4024,11 @@ bin_unhash(char *name, char **argv, Options ops, int func) * "unhash -m '*'" is legal, but not recommended. */ if (OPT_ISSET(ops,'m')) { for (; *argv; argv++) { + queue_signals(); /* expand argument */ tokenize(*argv); if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) { /* remove all nodes matching glob pattern */ - queue_signals(); for (i = 0; i < ht->hsize; i++) { for (hn = ht->nodes[i]; hn; hn = nhn) { /* record pointer to next, since we may free this one */ @@ -4039,12 +4039,12 @@ bin_unhash(char *name, char **argv, Options ops, int func) } } } - unqueue_signals(); } else { untokenize(*argv); zwarnnam(name, "bad pattern : %s", *argv); returnval = 1; } + unqueue_signals(); } /* If we didn't match anything, we return 1. */ if (!match) @@ -4127,18 +4127,18 @@ bin_alias(char *name, char **argv, Options ops, UNUSED(int func)) * glob patterns of aliases to display. */ if (OPT_ISSET(ops,'m')) { for (; *argv; argv++) { + queue_signals(); tokenize(*argv); /* expand argument */ if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) { /* display the matching aliases */ - queue_signals(); scanmatchtable(ht, pprog, 1, flags1, flags2, ht->printnode, printflags); - unqueue_signals(); } else { untokenize(*argv); zwarnnam(name, "bad pattern : %s", *argv); returnval = 1; } + unqueue_signals(); } return returnval; } @@ -4348,10 +4348,12 @@ bin_print(char *name, char **args, Options ops, int func) zwarnnam(name, "no pattern specified"); return 1; } + queue_signals(); tokenize(*args); if (!(pprog = patcompile(*args, PAT_STATIC, NULL))) { untokenize(*args); zwarnnam(name, "bad pattern: %s", *args); + unqueue_signals(); return 1; } for (t = p = ++args; *p; p++) @@ -4359,6 +4361,7 @@ bin_print(char *name, char **args, Options ops, int func) *t++ = *p; *t = NULL; first = args; + unqueue_signals(); if (fmt && !*args) return 0; } /* compute lengths, and interpret according to -P, -D, -e, etc. */ diff --git a/Src/cond.c b/Src/cond.c index 42e9de3..8ab0193 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -295,6 +295,8 @@ evalcond(Estate state, char *fromtest) int test, npat = state->pc[1]; Patprog pprog = state->prog->pats[npat]; + queue_signals(); + if (pprog == dummy_patprog1 || pprog == dummy_patprog2) { char *opat; int save; @@ -308,6 +310,7 @@ evalcond(Estate state, char *fromtest) if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC), NULL))) { zwarnnam(fromtest, "bad pattern: %s", right); + unqueue_signals(); return 2; } else if (save) @@ -316,6 +319,8 @@ evalcond(Estate state, char *fromtest) state->pc += 2; test = (pprog && pattry(pprog, left)); + unqueue_signals(); + return !(ctype == COND_STRNEQ ? !test : test); } case COND_STRLT: diff --git a/Src/glob.c b/Src/glob.c index 623e6f1..ff6b258 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2462,13 +2462,20 @@ xpandbraces(LinkList list, LinkNode *np) int matchpat(char *a, char *b) { - Patprog p = patcompile(b, PAT_STATIC, NULL); + Patprog p; + int ret; - if (!p) { + queue_signals(); /* Protect PAT_STATIC */ + + if (!(p = patcompile(b, PAT_STATIC, NULL))) { zerr("bad pattern: %s", b); - return 0; - } - return pattry(p, a); + ret = 0; + } else + ret = pattry(p, a); + + unqueue_signals(); + + return ret; } /* do the ${foo%%bar}, ${foo#bar} stuff */ diff --git a/Src/loop.c b/Src/loop.c index ae87b2f..f7eae30 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -620,7 +620,9 @@ execcase(Estate state, int do_exec) spprog = state->prog->pats + npat; pprog = NULL; pat = NULL; - + + queue_signals(); + if (isset(XTRACE)) { int htok = 0; pat = dupstring(ecrawstr(state->prog, state->pc, &htok)); @@ -657,6 +659,8 @@ execcase(Estate state, int do_exec) patok = anypatok = 1; state->pc += 2; nalts--; + + unqueue_signals(); } state->pc += 2 * nalts; if (isset(XTRACE)) { diff --git a/Src/options.c b/Src/options.c index e0b67d2..2b5795b 100644 --- a/Src/options.c +++ b/Src/options.c @@ -647,7 +647,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) /* Expand the current arg. */ tokenize(s); - if (!(pprog = patcompile(s, PAT_STATIC, NULL))) { + if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) { zwarnnam(nam, "bad pattern: %s", *args); continue; } diff --git a/Src/parse.c b/Src/parse.c index 314cc09..699ea49 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -3413,6 +3413,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map, for (; *names; names++) { tokenize(pat = dupstring(*names)); + /* Signal-safe here, caller queues signals */ if (!(pprog = patcompile(pat, PAT_STATIC, NULL))) { zwarnnam(nam, "bad pattern: %s", *names); close(dfd);