From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16573 invoked by alias); 28 Jul 2013 17:26:20 -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: 31611 Received: (qmail 12410 invoked from network); 28 Jul 2013 17:26:15 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 Received-SPF: neutral (ns1.primenet.com.au: 209.85.215.170 is neither permitted nor denied by SPF record at ntlworld.com) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-proxyuser-ip:date:from:to:subject:message-id:in-reply-to :references:x-mailer:mime-version:content-type :content-transfer-encoding:x-gm-message-state; bh=nqJfDbr0d7MtqWqOd3VCJLLBYGhCAYKi10Los+jub1g=; b=OPABUG5gKm+JVNtKJn9wCpOCdT3mMjzdz7xecDV2vlaXfDvGEzQvXFbdSCl9jEqgU4 o3gbnVAvm2qKbyHjvvBh01w2J7vi6RLcHMlDwKauY6/438Bs7838VBIz0HNP+wfMODxM NOUTE3qXh5zkSPkWJCbKgjSe9ivwCQg0Qttgl51cAPhOivb4jzwilZKs2pnmvzDn+HAs Lh51llPgyUaaOJPFHn+qxqWMKGYtOGfiDlgWpR4ymiF9CMPaTo1li8ZmUTRfDesgI1QU /gmhZ7ozJQm6tpgdmZylZch1+70BpQ3+WYsatyASmQs2mm8yzCECLYLF885lqwuRgZen 13pA== X-Received: by 10.14.94.136 with SMTP id n8mr16395314eef.97.1375031993537; Sun, 28 Jul 2013 10:19:53 -0700 (PDT) X-ProxyUser-IP: 86.6.30.159 Date: Sun, 28 Jul 2013 18:19:50 +0100 From: Peter Stephenson To: zsh-workers@zsh.org Subject: Re: Segfault completing: for f in 1; do <[here] x Message-ID: <20130728181950.02905913@pws-pc.ntlworld.com> In-Reply-To: <20130726102052.GB1752@goeswhere.com> References: <20130726102052.GB1752@goeswhere.com> X-Mailer: Claws Mail 3.8.0 (GTK+ 2.24.7; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Gm-Message-State: ALoCoQlAE5GJqRwCjA795C8Im02T2yxhmEFCAgV4Au22BgNJlQO0cnSheMF+uVII8axILDZLcOoZ [Sorry, meant to send this on Friday, which would have helped Bart's investigation. Comments welcome.] On Fri, 26 Jul 2013 11:20:52 +0100 solo-zsh@goeswhere.com wrote: > I'm getting a segfault when trying to complete after the "<" in: > for f in 1; do < x Yes, this is easy to reproduce. Unfortunately we're in one of those functions that nobody dares rewrite because it never really got written properly in the first place. The following tweaks fix the problem above and appear to be moderately safe. The incomprehensible "ins < 2" test safeguards against hitting the tricks used with completions after e.g. "repeat 2" which is done a hacky way. I don't understand why we need to set "ins" just to be able to detect the DOLOOP token on the next word, but I definitely don't dare change that. Could do with some playing with in similar cases with complicated syntax. Anyone with some free time is welcome to have a go at this function and report back even if they don't actually achieve any improvements (nobody else ever has). It's being so cheerful as keeps me going. diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 78a9fa4..610055c 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -1095,6 +1095,7 @@ get_comp_string(void) * the command word is not at index zero in the array. */ int redirpos; + int noword; char *s = NULL, *tmp, *p, *tt = NULL, rdop[20]; char *linptr, *u; @@ -1165,7 +1166,7 @@ get_comp_string(void) * and whatnot. */ do { - qsub = 0; + qsub = noword = 0; lincmd = ((incmdpos && !ins && !incond) || (oins == 2 && wordpos == 2) || @@ -1239,6 +1240,19 @@ get_comp_string(void) * leave the loop. */ if (tt) break; + if (ins < 2) { + /* + * Don't add this as a word, because we're about to start + * a new command line: pretend there's no string here. + * We don't dare do this if we're using one of the + * *really* gross hacks with ins to get later words + * to look like command words, because we don't + * understand how they work. Quite possibly we + * should be using a mechanism like the one here rather + * than the ins thing. + */ + noword = 1; + } /* Otherwise reset the variables we are collecting data in. */ wordpos = cp = rd = ins = redirpos = 0; tt0 = NULLTOK; @@ -1253,6 +1267,14 @@ get_comp_string(void) /* If everything before is a redirection, don't reset the index */ if (wordpos != redirpos) wordpos = redirpos = 0; + } else if (tok == SEPER) { + /* + * A following DOLOOP should cause us to reset to the start + * of the command line. For some reason we only recognise + * DOLOOP for this purpose (above) if ins is set. Why? + * Don't ask pointless questions. + */ + ins = 1; } if (!lexflags && tt0 == NULLTOK) { /* This is done when the lexer reached the word the cursor is on. */ @@ -1322,7 +1344,7 @@ get_comp_string(void) else if (tok == DAMPER) tokstr = "&&"; } - if (!tokstr) + if (!tokstr || noword) continue; /* Hack to allow completion after `repeat n do'. */ if (oins == 2 && !wordpos && !strcmp(tokstr, "do")) -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/