diff --git a/src/System.Management.Automation/engine/CommandSearcher.cs b/src/System.Management.Automation/engine/CommandSearcher.cs index 63bc666e123..a4ad2743ad8 100644 --- a/src/System.Management.Automation/engine/CommandSearcher.cs +++ b/src/System.Management.Automation/engine/CommandSearcher.cs @@ -1129,7 +1129,7 @@ private static bool ShouldSkipCommandResolutionForConstrainedLanguage(CommandInf resolvedPath = GetNextLiteralPathThatExists(path, out provider); } - if (WildcardPattern.ContainsWildcardCharacters(path) && + if (WildcardPattern.ContainsValidWildcardPattern(path) && ((resolvedPath == null) || (provider == null))) { // Let PowerShell resolve relative path with wildcards. diff --git a/src/System.Management.Automation/engine/GetCommandCommand.cs b/src/System.Management.Automation/engine/GetCommandCommand.cs index 9784cdc9ea8..e0f41ca22b2 100644 --- a/src/System.Management.Automation/engine/GetCommandCommand.cs +++ b/src/System.Management.Automation/engine/GetCommandCommand.cs @@ -54,7 +54,7 @@ public string[] Name { foreach (string commandName in value) { - if (WildcardPattern.ContainsWildcardCharacters(commandName)) + if (WildcardPattern.ContainsValidWildcardPattern(commandName)) { _nameContainsWildcard = true; break; @@ -812,7 +812,7 @@ private void AccumulateMatchingCommands(IEnumerable commandNames) moduleName = this.Module[0]; } - bool isPattern = WildcardPattern.ContainsWildcardCharacters(plainCommandName) || UseAbbreviationExpansion || UseFuzzyMatching; + bool isPattern = WildcardPattern.ContainsValidWildcardPattern(plainCommandName) || UseAbbreviationExpansion || UseFuzzyMatching; if (isPattern) { options |= SearchResolutionOptions.CommandNameIsPattern; diff --git a/src/System.Management.Automation/engine/regex.cs b/src/System.Management.Automation/engine/regex.cs index 4efe1ff436a..84c30af449a 100644 --- a/src/System.Management.Automation/engine/regex.cs +++ b/src/System.Management.Automation/engine/regex.cs @@ -314,6 +314,70 @@ public static bool ContainsWildcardCharacters(string pattern) return result; } + /// FIXME + /// For invalid wildcard pattern, it currently only check if there is + /// unclosed bracket. Need to find a better solution and rewrite this. + /// + /// + /// Checks to see if the given string might contains wildcard pattern. + /// + /// + /// String which needs to be checked + /// + /// + /// true if the string does not contain invalid wildcard pattern, + /// false otherwise. + /// + /// + /// Currently string contains { '*', '?' } or both { '[', ']' } is + /// considered to be properly a wildcard pattern and + /// '`' is the escape character. + /// + internal static bool ContainsValidWildcardPattern(string pattern) + { + if (string.IsNullOrEmpty(pattern)) + { + return false; + } + + bool hasWildcard = false; + bool openBracket = false; + + for (int index = 0; index < pattern.Length; ++index) + { + switch (pattern[index]) + { + case '*': + case '?': + hasWildcard = true; + break; + + case '[': + hasWildcard = true; + openBracket = true; + break; + + case ']': + // ']' is wildcard only if '[' exists + // so we do not set hasWildcard here + openBracket = false; + break; + + // If it is an escape character then advance past + // the next character + case escapeChar: + ++index; + break; + } + } + + if (openBracket) { + return false; + } + + return hasWildcard; + } + /// /// Unescapes any escaped characters in the input string. /// diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 index 6f4cf9aa778..c330e526db6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 @@ -7,11 +7,13 @@ Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { # Create temporary EXE command files $file1 = Setup -f WildCardCommandA.exe -pass $file2 = Setup -f WildCardCommand[B].exe -pass + $file3 = Setup -f [.exe -pass #$null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore #$null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore if ( $IsLinux -or $IsMacOS ) { /bin/chmod a+rw "$file1" /bin/chmod a+rw "$file2" + /bin/chmod a+rw "$file3" } $commandInfo = Get-Command Get-Date -ShowCommandInfo } @@ -54,6 +56,11 @@ Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { $result | Should -Not -BeNullOrEmpty $result | Should -Be WildCardCommand[B].exe + # This should find the file [.exe + $result = Get-Command -Name .\[.exe -Type Application + $result | Should -Not -BeNullOrEmpty + $result | Should -BeExactly [.exe + Pop-Location }