Skip to content

Command line parsing bug: spaces and trailing backslash #4358

Closed

Description

This 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.0

Activity

  1. mklement0 commented on Jul 28, 2017

    @mklement0
    Contributor

    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)

  2. SteveL-MSFT commented on Jul 28, 2017

    @SteveL-MSFT
    Member

    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.

  3. added this to the milestone on Jul 28, 2017
  4. added
    Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributors
    on Jul 30, 2017
  5. akervinen commented on Jul 30, 2017

    @akervinen
    Author

    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\'
    .\test 2"
    

    A shell that has a broken auto-complete for directories is... inconvenient.

  6. SteveL-MSFT commented on Jul 30, 2017

    @SteveL-MSFT
    Member

    Aleksi Kervinen (@akervinen) I see, every time with a space is definitely a concern

  7. modified the milestones: , , on Jul 30, 2017
  8. removed
    Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributors
    on Jul 31, 2017
  9. added
    Issue-BugIssue has been identified as a bug in the product
    and removed
    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif
    on Jul 31, 2017
  10. 6 remaining items

  11. JVimes commented on Sep 12, 2017

    @JVimes

    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!

  12. daxian-dbw commented on Sep 19, 2017

    @daxian-dbw
    Member

    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?

  13. mklement0 commented on Sep 19, 2017

    @mklement0
    Contributor

    Dongbo Wang (@daxian-dbw):

    My sense is that once this RFC proposal by TSlivede is implemented, it will cover this scenario too, so we probably don't need a separate fix for this specific issue.

    For background, see #1995 (comment)

  14. TSlivede commented on Sep 19, 2017

    @TSlivede

    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.

  15. SteveL-MSFT commented on Sep 19, 2017

    @SteveL-MSFT
    Member

    TSlivede makes sense. Dupe of #1995

  16. SteveL-MSFT commented on Oct 1, 2017

    @SteveL-MSFT
    Member

    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.

  17. triynko commented on Sep 21, 2021

    @triynko

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Issue-BugIssue has been identified as a bug in the productResolution-FixedThe issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtime

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions