GeezerVison is showing github.com — Command line parsing bug: spaces and trailing backslash · Issue #4358 · PowerShell/PowerShell
Command line parsing bug: spaces and trailing backslash #4358DescriptionThis has already been posted on UserVoice (here), but appears to still happen in 6.0.
Steps to reproduce
Using any .exe capable of outputting its command line arguments:
PS X:\scratch> .\ps-args-test.exe .\test1\ '.\test 2\' .\test1\
Auto-completion uses this format with a trailing backslash, so it's expected to work correctly.
Expected behavior
.\test1\
.\test 2\
.\test1\
Actual behavior
.\test1\
.\test 2" .\test1\
Environment data
> $PSVersionTable
Name Value
---- -----
PSVersion 6.0.0-beta
PSEdition Core
GitCommitId v6.0.0-beta.4
OS Microsoft Windows 10.0.14393
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0Reacted by Michael Klement and John Activitymklement0 commented on Jul 28, 2017 Ilya (@iSazonov):
This is only indirectly related to IntelliSense (which suggests passing the arguments like that).
The real issue is how the command line is rebuilt behind the scenes by PowerShell:
Argument list .\test1\ '.\test 2\' .\test1\ is translated to .\test1\ ".\test 2\" .\test1\ behind the scenes, which any external utility that uses \ as the escape character (most of them) parses as demonstrated in the initial post, causing the initial argument partitioning to be misinterpreted:
- The 2nd
" in ".\test 2\", due to being preceded by \ is interpreted as an escaped ", causing the remainder of the string - despite a then-missing closing " to be interpreted as part of the same argument.
The - cumbersome - workaround on Windows is to add an extra \, though, given that PowerShell does re-quoting behind the scenes (as is necessary on Windows), the fix is to let PowerShell do that automatically:
> .\ps-args-test.exe .\test1\ '.\test 2\\' .\test1\ # Note the '\\'
The - proper, hopefully-soon - fix on Unix platforms is to pass the arguments as an array of literals to the target utility, as is the norm on Unix platforms, bypassing such issues altogether. (Re-quoting behind the scenes is unnecessary on Unix platforms and should be avoided altogether.)
cc Steve Lee (@SteveL-MSFT) SteveL-MSFT commented on Jul 28, 2017 Unless I hear otherwise, this doesn't seem to be a common use case. I think we can fix in 6.1.0 unless someone from the community submits a PR. added this to the This milestone has been deleted milestone on Jul 28, 2017akervinen commented on Jul 30, 2017 I'd argue it's common since it happens every time I auto-complete a directory name with a space unless I remove the trailing slash manually. My example was a bit incomplete I think, since the extra quote is also inserted with just one argument.
PS X:\scratch> .\ps-args-test.exe '.\test 2\'
A shell that has a broken auto-complete for directories is... inconvenient. Reacted by Michael Klement, Byte Northbridge and Andrew Tapia SteveL-MSFT commented on Jul 30, 2017 Reacted by Michael Klement and Andrew Tapia modified the milestones: This milestone has been deleted, This milestone has been deleted, This milestone has been deleted on Jul 30, 2017JVimes commented on Sep 12, 2017 Just lost an hour wondering why git status wouldn't work with -C. And a number of RoboCopy folks lost time to it.
This use case gets hit! daxian-dbw commented on Sep 19, 2017
The - cumbersome - workaround on Windows is to add an extra , though, given that PowerShell does re-quoting behind the scenes (as is necessary on Windows), the fix is to let PowerShell do that automatically:
.\ps-args-test.exe .\test1\ '.\test 2\' .\test1\ # Note the '\'
Michael Klement (@mklement0) Do you think we should do this fix for now or shall we wait until https://github.com/dotnet/corefx/issues/23592 is addressed?
I'm trying to do this fix now but having some trouble figuring out the reasonable behavior handling the trailing backslashes of an arg string. When the arg string needs to be quoted, the trailing backslashes will escape each other and if there are odd number of backslashes, then the closing quote will be misinterpreted, for example:
PS> testexe.exe -echoargs 'test \'
Arg 0 is <test ">
PS> testexe.exe -echoargs 'test \\'
Arg 0 is <test \>
PS> testexe.exe -echoargs 'test \\\'
Arg 0 is <test \">
PS> testexe.exe -echoargs 'test \\\\'
Arg 0 is <test \\>
Now, we think the resulting " is confusing, and the ending \ should be preserved when passing to the native command. As a result, we will see behaviors like this:
PS> testexe.exe -echoargs 'test \'
Arg 0 is <test \>
PS> testexe.exe -echoargs 'test \\'
Arg 0 is <test \>
PS> testexe.exe -echoargs 'test \\\'
Arg 0 is <test \\>
PS> testexe.exe -echoargs 'test \\\\'
Arg 0 is <test \\>
You can see that when there is an odd number of backslashes, the ending backslash will be preserved, which makes the odd number of trailing backslashes always behave as (odd number + 1) trailing backslashes. Does this look like a reasonable behavior? mklement0 commented on Sep 19, 2017 Reacted by Dongbo Wang and TSlivede TSlivede commented on Sep 19, 2017 Yes, that's true. My RFC-Proposal (or any other fix for #1995) should also fix this. Basically we could rename #1995 to something like "Arguments for external executables aren't correctly escaped". In that case this issue could be closed as duplicate. Reacted by Michael Klement SteveL-MSFT commented on Sep 19, 2017 SteveL-MSFT commented on Oct 1, 2017 I'm separating this out from the uber issue of args to native commands which might be resolved by a future corefx api. I'll see if there is something we can do to solve this one sooner. triynko commented on Sep 21, 2021 This bug causes all kinds of problem in Jenkins builds. Trying to set any ENV variable to a path that ends in a backslash causes this.
For example, if you try to call setx 'MY_PATH' 'C:\folder1\folders' /M;
It ends up setting MYPATH to "C:\folder1\folder2" /M"
So instead of the value ending in a backslash, it ends with a double quote, a space, a forward slash, and a capital M. I happen to be setting a SignalFx environment home path, so it ends up crashing the entire profiler process.
It doesn't get more wrong that that. And Jenkins is just tied to this Powershell version (v5.1.19041.1023) so there's no fixing it. Just literally cannot pass any Powershell arguments using single quotes when the string ends in a backslash.
The PSReadline dependency implicated here is the same problematic project that prevents more than 50 characters from being pasted into docker container when powershell is active (works fine when basic cmd.exe is active instead) to this very day.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|