Skip to content

Commit 01b1b46

Browse files
Fix potential erroneous load of assembly
This change makes the assembly resolve handler be more strict when checking whether or not to load the YamlDotNet assembly. This should prevent accidentally loading the YamlDotNet assembly as a result of a request coming from another assembly that is looking to load a different assembly. Signed-off-by: Gabriel Adrian Samfira <[email protected]>
1 parent 18c7894 commit 01b1b46

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

powershell-yaml.psm1

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,33 +34,40 @@ function Invoke-LoadFile {
3434
[string]$assemblyPath
3535
)
3636

37-
$global:powershellYamlDotNetAssemblyPath = Join-Path $assemblyPath "YamlDotNet.dll"
37+
$powershellYamlDotNetAssemblyPath = Join-Path $assemblyPath "YamlDotNet.dll"
3838
$serializerAssemblyPath = Join-Path $assemblyPath "PowerShellYamlSerializer.dll"
3939
$yamlAssembly = [Reflection.Assembly]::LoadFile($powershellYamlDotNetAssemblyPath)
4040
$serializerAssembly = [Reflection.Assembly]::LoadFile($serializerAssemblyPath)
4141

4242
if ($PSVersionTable['PSEdition'] -eq 'Core') {
4343
# Register the AssemblyResolve event to load dependencies manually. This seems to be needed only on
4444
# PowerShell Core.
45-
[System.AppDomain]::CurrentDomain.add_AssemblyResolve({
45+
$resolver = {
4646
param ($snd, $e)
47+
# This event only needs to run once when the Invoke-LoadFile function is called.
48+
# If it's called again, the variables defined in this functions will not be available,
49+
# so we can safely ignore the event.
50+
if (-not $serializerAssemblyPath -or -not $powershellYamlDotNetAssemblyPath) {
51+
return $null
52+
}
4753
# Load YamlDotNet if it's requested by PowerShellYamlSerializer. Ignore other requests as they might
4854
# originate from other assemblies that are not part of this module and which might have different
4955
# versions of the module that they need to load.
50-
if ($e.Name -like "*YamlDotNet*" -and $e.RequestingAssembly -like "*PowerShellYamlSerializer*" ) {
56+
if ($e.Name -match "^YamlDotNet,*" -and $e.RequestingAssembly.Location -eq $serializerAssemblyPath) {
5157
return [System.Reflection.Assembly]::LoadFile($powershellYamlDotNetAssemblyPath)
5258
}
5359

5460
return $null
55-
})
61+
}
62+
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($resolver)
5663
# Load the StringQuotingEmitter from PowerShellYamlSerializer to force the resolver handler to fire once.
57-
# This will load the YamlDotNet assembly and expand the global variable $powershellYamlDotNetAssemblyPath.
58-
# We then remove it to avoid polluting the global scope.
5964
# This is an ugly hack I am not happy with.
6065
$serializerAssembly.GetType("StringQuotingEmitter") | Out-Null
66+
67+
# Remove the resolver handler after it has been used.
68+
[System.AppDomain]::CurrentDomain.remove_AssemblyResolve($resolver)
6169
}
6270

63-
Remove-Variable -Name powershellYamlDotNetAssemblyPath -Scope Global
6471
return @{ "yaml"= $yamlAssembly; "quoted" = $serializerAssembly }
6572
}
6673

0 commit comments

Comments
 (0)