zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.stephenson@samsung.com>
To: "zsh-workers@zsh.org" <zsh-workers@zsh.org>
Subject: Re: Global alias mangles input in 5.0.8
Date: Thu, 02 Jul 2015 09:45:43 +0100	[thread overview]
Message-ID: <20150702094543.34a7b477@pwslap01u.europe.root.pri> (raw)
In-Reply-To: <20150701212612.0f1947f3@ntlworld.com>

On Wed, 1 Jul 2015 21:26:12 +0100
Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> On Wed, 01 Jul 2015 10:23:57 +0100
> Peter Stephenson <p.stephenson@samsung.com> wrote:
> > On Wed, 1 Jul 2015 00:48:23 -0400
> > fcook <fcook@protonmail.com> wrote:
> > > I'm running on x86-64 Arch Linux, and noticing what looks like a bug doing the following:
> > > 
> > > > alias -g '$'='4<<('
> > > 
> > > > cat /proc/self/fd/4 $ ls )
> > > 
> > > But under zsh 5.0.8, I get an error: "zsh: no such file or directory: s )".
> 
> I'm not sure why they don't happen with $(, but the reason is that we
> have started to parse the complete (...) as a string so we can match
> the correct closing parenthesis, and then we encounter the end of the
> alias.  We backtrack because alias expansion occurs after the lexer,
> while we're tracking the string at the level of input --- however, in
> this case the alias was already being expanded when we found the "(",
> so we backtrack too far.  The fix is not to do that.

OK, I've found the mistake.  One of the mistakes.

In this case we shouldn't actually backtrack at all, not only not beyond
the start, because our text is coming from the entire remainder of the
alias.  The previous fix failed in the case shown in the new test.

This one is slightly simpler anyway (single-line changes in three
places, not counting removing the old patch).

pws


diff --git a/Src/input.c b/Src/input.c
index 4a5bf89..613f89a 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -591,7 +591,7 @@ inpoptop(void)
 	     * history is before, but they're both pushed onto
 	     * the input stack.
 	     */
-	    if ((inbufflags & (INP_ALIAS|INP_HIST)) == INP_ALIAS)
+	    if ((inbufflags & (INP_ALIAS|INP_HIST|INP_RAW_KEEP)) == INP_ALIAS)
 		zshlex_raw_back();
 	}
     }
diff --git a/Src/lex.c b/Src/lex.c
index 910773c..b0cd963 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -162,7 +162,7 @@ static int lex_add_raw;
 
 /* variables associated with the above */
 
-static char *tokstr_raw, *lexbuf_ptr_start;
+static char *tokstr_raw;
 static struct lexbufstate lexbuf_raw;
 
 /* text of punctuation tokens */
@@ -229,13 +229,12 @@ lex_context_save(struct lex_stack *ls, int toplevel)
     ls->lex_add_raw = lex_add_raw;
     ls->tokstr_raw = tokstr_raw;
     ls->lexbuf_raw = lexbuf_raw;
-    ls->lexbuf_ptr_start = lexbuf_ptr_start;
     ls->lexstop = lexstop;
     ls->toklineno = toklineno;
 
     tokstr = zshlextext = lexbuf.ptr = NULL;
     lexbuf.siz = 256;
-    tokstr_raw = lexbuf_raw.ptr = lexbuf_ptr_start = NULL;
+    tokstr_raw = lexbuf_raw.ptr = NULL;
     lexbuf_raw.siz = lexbuf_raw.len = lex_add_raw = 0;
 }
 
@@ -258,7 +257,6 @@ lex_context_restore(const struct lex_stack *ls, int toplevel)
     lex_add_raw = ls->lex_add_raw;
     tokstr_raw = ls->tokstr_raw;
     lexbuf_raw = ls->lexbuf_raw;
-    lexbuf_ptr_start = ls->lexbuf_ptr_start;
     lexstop = ls->lexstop;
     toklineno = ls->toklineno;
 }
@@ -1884,7 +1882,7 @@ zshlex_raw_add(int c)
 void
 zshlex_raw_back(void)
 {
-    if (!lex_add_raw || lexbuf_raw.ptr == lexbuf_ptr_start)
+    if (!lex_add_raw)
 	return;
     lexbuf_raw.ptr--;
     lexbuf_raw.len--;
@@ -1995,7 +1993,7 @@ skipcomm(void)
     cmdpop();
     return lexstop;
 #else
-    char *new_tokstr, *new_lexbuf_ptr_start;
+    char *new_tokstr;
     int new_lexstop, new_lex_add_raw;
     struct lexbufstate new_lexbuf;
 
@@ -2023,6 +2021,18 @@ skipcomm(void)
 	new_tokstr = tokstr;
 	new_lexbuf = lexbuf;
 
+	/*
+	 * If we're expanding an alias at this point, we need the whole
+	 * remaining text as part of the string for the command in
+	 * parentheses, so don't backtrack.  This is different from the
+	 * usual case where the alias is fully within the command, where
+	 * we want the unexpanded text so that it will be expanded
+	 * again when the command in the parentheses is executed.
+	 *
+	 * I never wanted to be a software engineer, you know.
+	 */
+	if (inbufflags & INP_ALIAS)
+	    inbufflags |= INP_RAW_KEEP;
 	zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
 	hist_in_word(1);
     } else {
@@ -2042,7 +2052,6 @@ skipcomm(void)
     }
     tokstr_raw = new_tokstr;
     lexbuf_raw = new_lexbuf;
-    lexbuf_ptr_start = lexbuf_raw.ptr;
     lex_add_raw = new_lex_add_raw;
     /*
      * Don't do any ZLE specials down here: they're only needed
@@ -2067,7 +2076,6 @@ skipcomm(void)
      */
     new_tokstr = tokstr_raw;
     new_lexbuf = lexbuf_raw;
-    new_lexbuf_ptr_start = lexbuf_ptr_start;
     /*
      * We're also going to propagate the lexical state:
      * if we couldn't parse the command substitution we
@@ -2083,7 +2091,6 @@ skipcomm(void)
 	 */
 	tokstr_raw = new_tokstr;
 	lexbuf_raw = new_lexbuf;
-	lexbuf_ptr_start = new_lexbuf_ptr_start;
     } else {
 	if (!new_lexstop) {
 	    /* Ignore the ')' added on input */
@@ -2098,7 +2105,6 @@ skipcomm(void)
 	tokstr = new_tokstr;
 	lexbuf = new_lexbuf;
 	lexstop = new_lexstop;
-	lexbuf_ptr_start = (char *)NULL;
 	hist_in_word(0);
     }
 
diff --git a/Src/zsh.h b/Src/zsh.h
index d11d4fe..69fef33 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -425,6 +425,7 @@ enum {
 #define INP_HISTCONT  (1<<5)	/* stack is continued from history expn.   */
 #define INP_LINENO    (1<<6)    /* update line number                      */
 #define INP_APPEND    (1<<7)    /* Append new lines to allow backup        */
+#define INP_RAW_KEEP  (1<<8)    /* Input needed in raw mode even if alias  */
 
 /* Flags for metafy */
 #define META_REALLOC	0
@@ -2801,7 +2802,6 @@ struct lex_stack {
     int lex_add_raw;
     char *tokstr_raw;
     struct lexbufstate lexbuf_raw;
-    char *lexbuf_ptr_start;
     int lexstop;
     zlong toklineno;
 };
diff --git a/Test/D03procsubst.ztst b/Test/D03procsubst.ztst
index 07ec639..7b87589 100644
--- a/Test/D03procsubst.ztst
+++ b/Test/D03procsubst.ztst
@@ -121,3 +121,8 @@
   eval 'foo echo this is bound to work)'
 0:backtacking within command string parsing with alias still pending
 >this is bound to work
+
+  alias foo='cat <( print'
+  eval 'foo here is some output)'
+0:full alias expanded when substitution starts in alias
+>here is some output


      reply	other threads:[~2015-07-02  8:45 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-01  4:48 fcook
2015-07-01  9:23 ` Peter Stephenson
2015-07-01 20:26   ` Peter Stephenson
2015-07-02  8:45     ` Peter Stephenson [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150702094543.34a7b477@pwslap01u.europe.root.pri \
    --to=p.stephenson@samsung.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).