zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: a='foo"'; echo ${a/foo"/"bar} outputs bar
Date: Mon, 12 Dec 2022 22:21:24 -0800	[thread overview]
Message-ID: <CAH+w=7ZZwEpA9Wekz5wEQgkoDT0SQ6ht2VkmYgAYtx6zqoNs9g@mail.gmail.com> (raw)
In-Reply-To: <20221211175001.u7dqfrnnzylsbjan@chazelas.org>

On Sun, Dec 11, 2022 at 9:50 AM Stephane Chazelas <stephane@chazelas.org> wrote:
>
> $ a='foo"'
> $ echo ${a/foo"/"bar}
> bar
>
> Whether quotes should escape the "/" is not clearly documented,
> though the doc does tell us to use backslash for that.

The whole expression only works because the quotes are balanced:

% echo ${x/foo"/bar}
braceparam dquote>

Clearly something a little wacky is going on here.

> However the fact that the first " is taken as being part of the
> pattern while the second one is removed doesn't make much sense.

This is the fault of singsub() called from line 2670 of
compgetmatch(), which eventually calls remnulargs() via prefork(),
which deletes the Dnull representing the double-quote.  This is only a
problem because an unbalanced quote was able to sneak through.

This was actually caught at paramsubst() line 3118:
                haserr = parse_subst_string(s);
This returned haserr == 1, but the only effect of that is that the
string is retokenized at line 3124.  If you use ${(X)x/foo"/"bar} you
get
  zsh: unmatched "

Next question is where this should be fixed.  The following works for
double-quotes, but not single because of special handling required for
$'...' -- so should be considered only a proof of how the substitution
could work with more conventional quoting.  All tests still pass with
the below.

diff --git a/Src/subst.c b/Src/subst.c
index 0f98e6ea3..86ee1dad8 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2911,6 +2911,9 @@ paramsubst(LinkList l, LinkNode n, char **str,
int qt, int pf_flags,
             else
             ptr++;
         }
+        if (c == Dnull)
+            while (ptr[1] && ptr[1] != c)
+            ptr++;
         }
         replstr = (*ptr && ptr[1]) ? ptr+1 : "";
         *ptr = '\0';


  reply	other threads:[~2022-12-13  6:22 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-11 17:50 Stephane Chazelas
2022-12-13  6:21 ` Bart Schaefer [this message]
2023-08-07  2:36   ` Bart Schaefer
2023-10-04  4:20     ` Bart Schaefer
2023-10-17 16:44       ` Bart Schaefer

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='CAH+w=7ZZwEpA9Wekz5wEQgkoDT0SQ6ht2VkmYgAYtx6zqoNs9g@mail.gmail.com' \
    --to=schaefer@brasslantern.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).