Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{x,y,z} parameter expansion is not escaped #4629

Closed
mqudsi opened this issue Dec 30, 2017 · 3 comments
Closed

{x,y,z} parameter expansion is not escaped #4629

mqudsi opened this issue Dec 30, 2017 · 3 comments
Labels

Comments

@mqudsi
Copy link
Contributor

mqudsi commented Dec 30, 2017

Fish parameters are, as a rule, escaped before being injected into fish commands:

mqudsi@freebsd> echo hello > hello\ world.txt
mqudsi@freebsd> file (echo hello world.txt)
hello world.txt: ASCII text

However, the result of braces expansion is not correctly escaped, and there's no easy way to escape to manually escape it as introducing quotes around the parameter breaks the expansion:

mqudsi@freebsd> echo -n hello\ {1,2,3}.txt\n
hello 1.txt
 hello 2.txt
 hello 3.txt

As you can see, after the first parameter, echo is being passed two separate arguments hello and #.txt, leading to the extra space in front of the words.

Wrapping the arguments in quotes leads to the following:

mqudsi@freebsd> echo -n "hello\ {1,2,3}.txt\n"
hello\ {1,2,3}.txt\n

While attempting to work around the issue by inserting escaped quotes into the original string (under the presumption that the contents of the string are not being escaped after replace and before injection) leads to the quotes being correctly escaped, preventing the desired result:

mqudsi@freebsd> echo -n \"hello\ {1,2,3}.txt\n\"                                                                                                     "hello 1.txt                                                                                                                                                       " "hello 2.txt                                                                                                                                                     " "hello 3.txt                                                                                                                                                     
"

It looks like the parameter expansion is happening after the argument splitting stage.

@floam floam added the bug Something that's not working as intended label Dec 31, 2017
@anordal
Copy link
Contributor

anordal commented Dec 31, 2017

echo is being passed two separate arguments hello and #.txt, leading to the extra space in front of the words.

I don't agree with that diagnosis. echo is being passed 3 arguments (each ending with \n), which echo dutifully prints with a space inbetween. I see no bug here.

Here is what I do to debug arguments:

~> printf '«%s»' hei\ {1,2,3}.txt\n
«hei 1.txt
»«hei 2.txt
»«hei 3.txt
»⏎

@faho
Copy link
Member

faho commented Dec 31, 2017

Here is what I do to debug arguments:

I use string escape, i.e.

> string escape -- hello\ {1,2,3}.txt\n
hello\ 1.txt\n
hello\ 2.txt\n
hello\ 3.txt\n

which means you actually get what I'd expect. You get the full argument with "1", then with "2" and then with "3". The full argument just happens to include a newline.

@mqudsi: I would assume what's throwing you off here is one of a couple of things:

  • We only split command substitutions ((command)) on newline. That means the \n here has no special meaning after being replaced with a newline character. It's "a character", as far as the rest is concerned. We don't need to escape the character, we just don't run the splitting.

Or in file (echo hello world.txt), the "hello world.txt" is not escaped to hello\ world.txt, it's just not split because there's no newline. If you have a file called hello\nworld.txt, this would have issues similar to bash's problem with spaces.

  • echo inserts spaces between its arguments (if "-s" has not been given). That's what's causing the weird indentation - because the spaces happen right after the newline.

That means if you want to have the output

hello 1.txt
hello 2.txt
hello 3.txt

use echo -s or printf '%s\n' hello\ {1,2,3}.txt.

I believe this is a misunderstanding, rather than a bug. Am I correct?

@faho faho added question and removed bug Something that's not working as intended labels Dec 31, 2017
@mqudsi
Copy link
Contributor Author

mqudsi commented Dec 31, 2017

Sorry, folks! I was trying to come up with a minimal repro for an issue and was confused by something completely different. I got the behavior of parameter expansion wrong, in particular, I confused it with that of parallel or xargs with a limit of 1, i.e. I presumed echo {1,2,3} would expand to 3 commands with 1 argument each and not 1 command with 3 arguments.

Thanks for setting me straight.

@mqudsi mqudsi closed this as completed Dec 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants