Skip to content

Native globbing doesn't respect bypassing via the escape character (backtick) in unquoted arguments #15959

Closed

Description

Prerequisites

Steps to reproduce

When calling external programs on Unix-like platforms, native globbing can be bypassed on demand with single- or double-quoting an argument; e.g., /bin/echo '*'

The same should work with selectively escaping globbing metacharacters with ` in unquoted arguments, but currently doesn't.

# On Unix
/bin/echo `*

Expected behavior

*

Actual behavior

The names of all files and directories are output, because globbing was unexpectedly still applied.

Error details

No response

Environment data

PowerShell Core 7.2.0-preview.8 on Unix-like platforms.

Visuals

No response

Activity

  1. added
    Issue-BugIssue has been identified as a bug in the product
    WG-Engine-Providersbuilt-in PowerShell providers such as FileSystem, Certificates, Registry, etc.
    on Aug 20, 2021
  2. 237dmitry commented on Aug 20, 2021

    @237dmitry

    Why expected behavior is * output? In bash echo * outputs string with all files and directories in current location (space separated). In pwsh /bin/echo `* outputs string of unhidden files and directories

  3. mklement0 commented on Aug 20, 2021

    @mklement0
    ContributorAuthor

    Because `* is an escaped * character, to be used verbatim - just like '*', which does bypass native globbing.

  4. 237dmitry commented on Aug 20, 2021

    @237dmitry

    Escaping is not equivalent quoting. You pass the escaped character to receive it as is. So that it is not lost or it is not interpreted in some other way. So /bin/echo gets everything as it is. Maybe I'm wrong, but that's how I understand this.

  5. mklement0 commented on Aug 20, 2021

    @mklement0
    ContributorAuthor

    Yes, escaping is equivalent to quoting - just two different ways of achieving the same effect; compare Write-Output `| to Write-Output '|'

    You pass the escaped character to receive it as is

    That's precisely the point, and passing * as-is means just that: the external executable /bin/echo should receive * verbatim and therefore also print it verbatim.

    Note that no (native) shell is involved in such a call.

    It is PowerShell that emulates a feature of POSIX-compatible shells - hence the name native globbing - and the external utility being invoked sees the results of that. And if I'm telling PowerShell to treat a character verbatim, it should therefore not apply this emulation - irrespective of the syntax form used.

  6. 237dmitry commented on Aug 20, 2021

    @237dmitry

    compare Write-Output `| to Write-Output '|'

    PS > /bin/echo `|
    |
    PS >

    Perhaps the * character is a special character for /bin/echo, which should еxplicitly be in quotation marks.

  7. mklement0 commented on Aug 20, 2021

    @mklement0
    ContributorAuthor

    No, * has no special meaning to /bin/echo.

    This is purely about PowerShell respecting the explicitly signaled intent to treat a character verbatim, which if unquoted or unescaped would have special meaning (a situational metacharacter that only acts a such when (a) calling external programs and (b) on Unix-like platforms only).

    (The same applies to ? and [.)

  8. mklement0 commented on Aug 20, 2021

    @mklement0
    ContributorAuthor

    And, to be clear, programs on Unix receive arguments as an array of verbatim values - they have no information about what particular shell with what particular quoting/escaping syntax was used to translate a command line into that array of verbatim values. For instance, /bin/echo `|, /bin/echo '|' and /bin/echo "|" all result in the same invocation of /bin/echo, namely with an argument array whose 2nd element contains verbatim | (the 1st element is the executable name or path itself).

  9. vexx32 commented on Sep 3, 2021

    @vexx32
    Collaborator

    WG-Engine discussed this issue in today's meeting.

    Our opinion is that this issue with wildcards is not exclusive to the native command globbing behaviour — although, yes, the ability to use quotes to quietly bypass the globbing behaviour is specific to this experimental feature.

    Given that there is currently a workaround that will likely suffice for most use cases, which Michael Klement (@mklement0) outlines in the initial post, we would prefer effort be spent investigating more complete fixes for the issues with wildcard escaping that currently exist, rather than trying to design exceptions to the wildcard handling specifically for this feature. If a robust solution can be found to that issue (see #7999; there is also some relevant discussion in #7399), it would become trivial to incorporate the solution into the behaviour of this feature as well.

    Ideally the functionality of this feature should match the behaviour of wildcard globbing as implemented in provider cmdlets.

    Given that, we don't think this specific issue makes sense to fix in isolation, and it would be likely to result in additional confusion when such a workaround would subsequently fail to work with wildcards in other areas of pwsh.

  10. vexx32 commented on Sep 5, 2021

    @vexx32
    Collaborator

    Resolving this one as a duplicate of #7999 as the root cause is ultimately the wildcard handling.

  11. mklement0 commented on Sep 6, 2021

    @mklement0
    ContributorAuthor

    Just to note an important distinction, Rain Sallow (/u/ta11ow) (@vexx32):

    • Backtick escaping inconsistent #7999 is about how cmdlets / providers treat wildcard expressions that they see after the parameter binder has bound arguments. That is, Get-Item *, Get-Item `* (the bareword parsing eats the `), Get-Item '*', and Get-Item "*" are - and should be - equivalent, because Get-Item sees verbatim * in all cases.

    • By contrast, we're talking about an intentional anomaly when calling external programs on Unix, in service of emulating a different shell's behavior: as in POSIX-compatible shells, what matters is whether the argument is quoted / has individual metacharacters escaped (e.g., from Bash, compare echo * with echo \* / echo '*' / echo "*"), in which case no globbing must be applied.

      • Therefore, the solution must be implemented at the level of the code that parses the raw argument and decides whether native globbing is to be performed.
  12. vexx32 commented on Sep 6, 2021

    @vexx32
    Collaborator

    Yeah, I'd agree that the code path here is somewhat separate to the one originally mentioned in #7999. However, the problem is likely caused by similar handling of input -- both use WildcardPattern -- and I think we were all more or less in agreement that it would counterintuitive to implement a partial fix that only addresses this issue instead of generalising the fix to also resolve the original issue for #7999.

    I think it's definitely worth mentioning that in #7999 and we can incorporate this facet into the original issue as well. 🙂

  13. ghost closed this as completedon Sep 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-BugIssue has been identified as a bug in the productOS-LinuxOS-macOSResolution-DuplicateThe issue is a duplicate.WG-Engine-Providersbuilt-in PowerShell providers such as FileSystem, Certificates, Registry, etc.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions