From #8218.
Get-Module using a path in a fully qualified name will skip other constraints in the fully qualified name and be too permissive.
Steps to reproduce
Describe 'Get-Module -ListAvailable with path' {
BeforeAll {
$moduleName = 'Banana'
$modulePath = Join-Path $TestDrive $moduleName
$v1 = '1.2.3'
$v2 = '4.8.3'
$v1DirPath = Join-Path $modulePath $v1
$v2DirPath = Join-Path $modulePath $v2
$manifestV1Path = Join-Path $v1DirPath "$moduleName.psd1"
$manifestV2Path = Join-Path $v2DirPath "$moduleName.psd1"
New-Item -ItemType Directory $modulePath
New-Item -ItemType Directory -Path $v1DirPath
New-Item -ItemType Directory -Path $v2DirPath
New-ModuleManifest -Path $manifestV1Path -ModuleVersion $v1
New-ModuleManifest -Path $manifestV2Path -ModuleVersion $v2
}
It "Gets all versions by path" {
$modules = Get-Module -ListAvailable $modulePath | Sort-Object -Property Version
$modules | Should -HaveCount 2
$modules[0].Name | Should -BeExactly $moduleName
$modules[0].Path | Should -BeExactly $manifestV1Path
$modules[0].Version | Should -Be $v1
$modules[1].Name | Should -BeExactly $moduleName
$modules[1].Path | Should -BeExactly $manifestV2Path
$modules[1].Version | Should -Be $v2
}
It "Gets all versions by FullyQualifiedName with path with lower version" {
$modules = Get-Module -ListAvailable -FullyQualifiedName @{ ModuleName = $modulePath; ModuleVersion = '0.0' } | Sort-Object -Property Version
$modules | Should -HaveCount 2
$modules[0].Name | Should -BeExactly $moduleName
$modules[0].Path | Should -BeExactly $manifestV1Path
$modules[0].Version | Should -Be $v1
$modules[1].Name | Should -BeExactly $moduleName
$modules[1].Path | Should -BeExactly $manifestV2Path
$modules[1].Version | Should -Be $v2
}
It "Gets high version by FullyQualifiedName with path with high version" {
$modules = Get-Module -ListAvailable -FullyQualifiedName @{ ModuleName = $modulePath; ModuleVersion = '2.0' } | Sort-Object -Property Version
$modules | Should -HaveCount 1
$modules[0].Name | Should -BeExactly $moduleName
$modules[0].Path | Should -BeExactly $manifestV2Path
$modules[0].Version | Should -Be $v2
}
It "Gets low version by FullyQualifiedName with path with low maximum version" {
$modules = Get-Module -ListAvailable -FullyQualifiedName @{ ModuleName = $modulePath; MaximumVersion = '2.0' } | Sort-Object -Property Version
$modules | Should -HaveCount 1
$modules[0].Name | Should -BeExactly $moduleName
$modules[0].Path | Should -BeExactly $manifestV1Path
$modules[0].Version | Should -Be $v1
}
It "Gets low version by FullyQualifiedName with path with low maximum version and version" {
$modules = Get-Module -ListAvailable -FullyQualifiedName @{ ModuleName = $modulePath; MaximumVersion = '2.0'; ModuleVersion = '1.0' } | Sort-Object -Property Version
$modules | Should -HaveCount 1
$modules[0].Name | Should -BeExactly $moduleName
$modules[0].Path | Should -BeExactly $manifestV1Path
$modules[0].Version | Should -Be $v1
}
It "Gets correct version by FullyQualifiedName with path with required version" -TestCases @(
@{ Version = $v1 }
@{ Version = $v2 }
) {
param([version]$Version)
switch ($Version)
{
$v1
{
$expectedPath = $manifestV1Path
break
}
$v2
{
$expectedPath = $manifestV2Path
}
}
$modules = Get-Module -ListAvailable -FullyQualifiedName @{ ModuleName = $modulePath; RequiredVersion = $Version }
$modules | Should -HaveCount 1
$modules[0].Name | Should -BeExactly $moduleName
$modules[0].Path | Should -BeExactly $expectedPath
$modules[0].Version | Should -Be $Version
}
}
Expected behavior
All tests pass
Actual behavior
Tests with additional version checks in fully qualified names have their checks ignored.
This is of the following code:
|
// TODO: |
|
// moduleSpecification.Name may be a path and will not match module.Name when they refer to the same module. |
|
// This actually causes the module to be returned always, so other specification checks are skipped erroneously. |
|
// Instead we need to be able to look up or match modules by path as well (e.g. a new comparer for PSModuleInfo). |
|
|
|
// No table entry means we return the module |
|
if (!moduleSpecificationTable.TryGetValue(module.Name, out ModuleSpecification moduleSpecification)) |
|
{ |
|
yield return module; |
|
continue; |
|
} |
When a path is specified, the lookup fails and we (perversely) return the module.
From #8218.
Get-Moduleusing a path in a fully qualified name will skip other constraints in the fully qualified name and be too permissive.Steps to reproduce
Expected behavior
All tests pass
Actual behavior
Tests with additional version checks in fully qualified names have their checks ignored.
This is of the following code:
PowerShell/src/System.Management.Automation/engine/Modules/GetModuleCommand.cs
Lines 547 to 557 in 79f21b4
When a path is specified, the lookup fails and we (perversely) return the module.