diff --git a/src/System.Management.Automation/namespaces/LocationGlobber.cs b/src/System.Management.Automation/namespaces/LocationGlobber.cs index 16168a60753..718052aa123 100644 --- a/src/System.Management.Automation/namespaces/LocationGlobber.cs +++ b/src/System.Management.Automation/namespaces/LocationGlobber.cs @@ -1665,9 +1665,18 @@ internal static bool IsAbsolutePath(string path) if (index > 0) { - // We must have a drive specified - - result = true; + // see if there are any path separators before the colon which would mean the + // colon is part of a file or folder name and not a drive: ./foo:bar vs foo:bar + int separator = path.IndexOf(StringLiterals.DefaultPathSeparator, 0, index-1); + if (separator == -1) + { + separator = path.IndexOf(StringLiterals.AlternatePathSeparator, 0, index-1); + } + if (separator == -1 || index < separator) + { + // We must have a drive specified + result = true; + } } } while (false); @@ -3404,21 +3413,27 @@ private static string RemoveDriveQualifier(string path) string result = path; - // Find the drive separator + // Find the drive separator only if it's before a path separator int index = path.IndexOf(":", StringComparison.Ordinal); - if (index != -1) { - // Remove the \ or / if it follows the drive indicator - - if (path[index + 1] == '\\' || - path[index + 1] == '/') + int separator = path.IndexOf(StringLiterals.DefaultPathSeparator, 0, index); + if (separator == -1) { - ++index; + separator = path.IndexOf(StringLiterals.AlternatePathSeparator, 0, index); } + if (separator == -1 || index < separator) + { + // Remove the \ or / if it follows the drive indicator + if (path[index + 1] == '\\' || + path[index + 1] == '/') + { + ++index; + } - result = path.Substring(index + 1); + result = path.Substring(index + 1); + } } return result; diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 index 909cc24de08..afe6aa0d858 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 @@ -199,6 +199,43 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { New-Item -Path $testFile -ItemType File -Force -ErrorAction SilentlyContinue } } + + It "Set-Location on Unix succeeds with folder with colon: " -Skip:($IsWindows) -TestCases @( + @{path="\hello:world"}, + @{path="\:world"}, + @{path="/hello:"} + ) { + param($path) + try { + New-Item -Path "$testdrive$path" -ItemType Directory > $null + Set-Location "$testdrive" + Set-Location ".$path" + (Get-Location).Path | Should Be "$testdrive/$($path.Substring(1,$path.Length-1))" + } + finally { + Remove-Item -Path "$testdrive$path" -ErrorAction SilentlyContinue + } + } + + It "Get-Content on Unix succeeds with folder and file with colon: " -Skip:($IsWindows) -TestCases @( + @{path="\foo:bar.txt"}, + @{path="/foo:"}, + @{path="\:bar"} + ) { + param($path) + try { + $testPath = "$testdrive/hello:world" + New-Item -Path "$testPath" -ItemType Directory > $null + Set-Content -Path "$testPath$path" -Value "Hello" + $files = Get-ChildItem "$testPath" + $files.Count | Should Be 1 + $files[0].Name | Should BeExactly $path.Substring(1,$path.Length-1) + $files[0] | Get-Content | Should BeExactly "Hello" + } + finally { + Remove-Item -Path $testPath -Recurse -Force -ErrorAction SilentlyContinue + } + } } Context "Validate behavior when access is denied" {