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

Namespace variable notation unexpectedly treats paths as wildcard expressions #9225

Closed
mklement0 opened this issue Mar 25, 2019 · 7 comments
Closed
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-No Activity Issue has had no activity for 6 months or more WG-Engine-Providers built-in PowerShell providers such as FileSystem, Certificates, Registry, etc.

Comments

@mklement0
Copy link
Contributor

mklement0 commented Mar 25, 2019

Conceptually related: #4726.

Note: Fixing this issue would technically be a breaking change.

PowerShell treats the following:

${<drive>:<name>}

as if you had specified:

Get-Content -Path <drive>:<name>  # or, with assignment, Set-Content -Path ...

This notation - though often used with the Env: drive (e.g., $env:Path) - is little-known as a general paradigm named namespace variable notation, which is explained in this SO answer.

The problem is the use of -Path rather than -LiteralPath (conceptually speaking), because -Path interprets its argument as a wildcard expression.

By design, you can only ever target a single item with namespace notation and if you intentionally specify a wildcard that resolves to multiple items, the statement breaks.

There is no good reason for namespace notation to treat paths as wildcard expressions to begin with, just as it makes no sense to do so for executable invocations and redirections (see #4726).

The fact that they are treated as wildcards causes problems with item names that happen to look like wildcard expressions, in one of two ways:

  • You may not be able to create a new item, such as a new environment variable, at all.
  • Perhaps worse, you may inadvertently target a different, preexisting item.

Taking the example of wanting to assign to / query the value of an environment variable literally named [foo] with ${env:[foo]}, from this SO question:

Steps to reproduce

# Try to create env. var. literally named '[foo]'
${env:[foo]} = 'bar'
# Create a seemingly unrelated env. var. whose name happens to match
# [foo] *if interpreted as a wildcard expression*
$env:o = 'no'
# Get the value
${env:[foo]}

Expected behavior

bar

That is, implicit creation of the variable via namespace notation should succeed, as should subsequent retrieval.

Actual behavior

Cannot find path 'env:[foo]' because it does not exist.
no
  • That is, implicit creation of the variable failed, because the wildcard resolution of [foo] matched nothing and so there was effectively no variable name to assign to / create.

  • ${env:[foo]} unexpectedly retrieved the value of ${env:o}, because [foo] interpreted as a wildcard matches o.

The workaround is to use double `-escaping: ${env:``[foo``]}; that the escape char. must be doubled is an additional quirk - see #7999

Environment data

PowerShell Core 6.2.0-rc.1
Windows PowerShell v5.1
@mklement0 mklement0 added the Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a label Mar 25, 2019
@msftrncs
Copy link
Contributor

Isn't the wildcard behavior a function of the provider? In this case the ENV: provider, but in the case of a drive letter, its the file system provider. Does PowerShell need to tell the provider to accept it as a 'literal' path? I have also run in to the wildcard situation using the ENV provider using the namespace convention, but I think I was testing with a *.

The above example also gives a different error if the wildcard resolved to multiple items.

Cannot process variable because variable path 'env:[foo]' resolved to multiple items. You can get or set the variable value only one item at a time.
At line:1 char:1
+ ${env:[foo]}
+ ~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [], PSArgumentException
+ FullyQualifiedErrorId : Argument

The double backticking seems peculiar, as it only seems to be accepted as demonstrated, so it appears to be on purpose. It seems to be special to just the namespace variable notation.

At this point I would be willing to bet somewhere someone had a use for wildcard paths with the namespace variable notation, and so that's why this exists.

I am thinking about if these notations should be added to the PowerShell/EditorSyntax PR that I have been working on. I suspect they only apply to certain providers, of which those providers could be redefined or changed so there is probably no consistent way to scope these specific notations.

@vexx32
Copy link
Collaborator

vexx32 commented Mar 30, 2019

Namespace variable notation applies to all providers that have PSDrives available, but isn't usable with all of them. In order to be usable with this syntax, the provider has to implement IContentCmdletProvider (i.e., Get-Content has to be implemented for that provider).

It also won't resolve to the provider if the PSDrive name is already taken by an existing scope (e.g., a PSDrive named global won't work, because that's a defined scope name).

I think that this is most likely to be an accidental result of the default providers by default applying globbing unless it's specifically requested to process the path as literal. The fact that a path that does resolve to multiple items fails to do anything other than throw an error would appear to support that, I think. 😄

@mklement0
Copy link
Contributor Author

Thanks for the clarifications, @vexx32.

@msftrncs

At this point I would be willing to bet somewhere someone had a use for wildcard paths with the namespace variable notation, and so that's why this exists.

I think it's more likely accidental (I'm speculating), perhaps dating back to a time before the great -Path / -LiteralPath schism, when only wildcard expressions existed.

Similarly unhelpful behavior (accepting a wildcard, but requiring resolution to a single item):

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

2 similar comments
Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

@microsoft-github-policy-service microsoft-github-policy-service bot added Resolution-No Activity Issue has had no activity for 6 months or more labels Nov 16, 2023
Copy link
Contributor

This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-No Activity Issue has had no activity for 6 months or more WG-Engine-Providers built-in PowerShell providers such as FileSystem, Certificates, Registry, etc.
Projects
None yet
Development

No branches or pull requests

4 participants