Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 30 additions & 41 deletions src/coreclr/binder/assemblybindercommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,6 @@ HRESULT AssemblyBinderCommon::BindUsingHostAssemblyResolver(/* in */ INT_PTR pAs
HRESULT AssemblyBinderCommon::BindUsingPEImage(/* in */ AssemblyBinder* pBinder,
/* in */ BINDER_SPACE::AssemblyName *pAssemblyName,
/* in */ PEImage *pPEImage,
/* in */ bool excludeAppPaths,
/* [retval] [out] */ Assembly **ppAssembly)
{
HRESULT hr = E_FAIL;
Expand All @@ -1177,55 +1176,45 @@ HRESULT AssemblyBinderCommon::BindUsingPEImage(/* in */ AssemblyBinder* pBinder
// Lock the application context
CRITSEC_Holder contextLock(pApplicationContext->GetCriticalSectionCookie());

// Attempt uncached bind and register stream if possible
// We skip version compatibility check - so assemblies with same simple name will be reported
// as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check).
hr = BindByName(pApplicationContext,
pAssemblyName,
true, // skipFailureCaching
true, // skipVersionCompatibilityCheck
excludeAppPaths, // excludeAppPaths
&bindResult);
// Check if an assembly with the same name was already loaded.
Assembly *pAssembly = NULL;
hr = FindInExecutionContext(pApplicationContext, pAssemblyName, &pAssembly);

if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
if (hr == S_FALSE && pAssembly == NULL)
{
// No assembly with the same name was already loaded, so load from the stream
IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult));
}
else if (hr == S_OK)
else if (hr == S_OK && pAssembly != NULL)
{
if (bindResult.HaveResult())
{
// Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name
// does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being
// requested.
// An assembly with the same name was already loaded. We need to check the MVID
// to confirm it is the same assembly as the one being requested.

GUID incomingMVID;
GUID boundMVID;

// GetMVID can throw exception
EX_TRY
{
pPEImage->GetMVID(&incomingMVID);
bindResult.GetAssembly()->GetPEImage()->GetMVID(&boundMVID);
}
EX_CATCH
{
hr = GET_EXCEPTION()->GetHR();
goto Exit;
}
EX_END_CATCH
GUID incomingMVID;
GUID boundMVID;

// GetMVID can throw exception
EX_TRY
{
pPEImage->GetMVID(&incomingMVID);
pAssembly->GetPEImage()->GetMVID(&boundMVID);
}
EX_CATCH
{
hr = GET_EXCEPTION()->GetHR();
goto Exit;
}
EX_END_CATCH

mvidMismatch = incomingMVID != boundMVID;
if (mvidMismatch)
{
// MVIDs do not match, so fail the load.
IF_FAIL_GO(COR_E_FILELOAD);
}

// MVIDs match - request came in for the same assembly that was previously loaded.
// Let it through...
mvidMismatch = incomingMVID != boundMVID;
if (mvidMismatch)
{
// MVIDs do not match, so fail the load.
IF_FAIL_GO(COR_E_FILELOAD);
}

// MVIDs match - the assembly was previously loaded.
bindResult.SetResult(pAssembly, /*isInContext*/ true);
}

// Remember the post-bind version of the context
Expand Down
7 changes: 3 additions & 4 deletions src/coreclr/binder/customassemblybinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ Exit:;
}

HRESULT CustomAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage,
/* in */ bool excludeAppPaths,
/* [retval][out] */ BINDER_SPACE::Assembly **ppAssembly)
{
HRESULT hr = S_OK;
Expand All @@ -129,7 +128,7 @@ HRESULT CustomAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage,
IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
}

hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, excludeAppPaths, &pCoreCLRFoundAssembly);
hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, &pCoreCLRFoundAssembly);
if (hr == S_OK)
{
_ASSERTE(pCoreCLRFoundAssembly != NULL);
Expand Down Expand Up @@ -230,7 +229,7 @@ void CustomAssemblyBinder::PrepareForLoadContextRelease(INT_PTR ptrManagedStrong
// native LoaderAllocators of two collectible contexts in case the AssemblyLoadContext.Unload was called on the current
// context before returning from its AssemblyLoadContext.Load override or the context's Resolving event.
// But we need to release the LoaderAllocator so that it doesn't prevent completion of the final phase of unloading in
// some cases. It is safe to do as the AssemblyLoaderAllocator is guaranteed to be alive at least until the
// some cases. It is safe to do as the AssemblyLoaderAllocator is guaranteed to be alive at least until the
// CustomAssemblyBinder::ReleaseLoadContext is called, where we NULL this pointer.
m_pAssemblyLoaderAllocator->Release();

Expand Down Expand Up @@ -258,7 +257,7 @@ void CustomAssemblyBinder::ReleaseLoadContext()
DestroyHandle(handle);
SetAssemblyLoadContext((INT_PTR)NULL);

// The AssemblyLoaderAllocator is in a process of shutdown and should not be used
// The AssemblyLoaderAllocator is in a process of shutdown and should not be used
// after this point.
m_pAssemblyLoaderAllocator = NULL;
}
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/binder/defaultassemblybinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ Exit:;

#if !defined(DACCESS_COMPILE)
HRESULT DefaultAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage,
/* in */ bool excludeAppPaths,
/* [retval][out] */ BINDER_SPACE::Assembly **ppAssembly)
{
HRESULT hr = S_OK;
Expand Down Expand Up @@ -158,7 +157,7 @@ HRESULT DefaultAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage,
}
}

hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, excludeAppPaths, &pCoreCLRFoundAssembly);
hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, &pCoreCLRFoundAssembly);
if (hr == S_OK)
{
_ASSERTE(pCoreCLRFoundAssembly != NULL);
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/binder/inc/assemblybindercommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ namespace BINDER_SPACE
static HRESULT BindUsingPEImage(/* in */ AssemblyBinder *pBinder,
/* in */ BINDER_SPACE::AssemblyName *pAssemblyName,
/* in */ PEImage *pPEImage,
/* in */ bool excludeAppPaths,
/* [retval] [out] */ Assembly **ppAssembly);
#endif // !defined(DACCESS_COMPILE)

Expand Down
1 change: 0 additions & 1 deletion src/coreclr/binder/inc/customassemblybinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class CustomAssemblyBinder final : public AssemblyBinder
public:

HRESULT BindUsingPEImage(PEImage* pPEImage,
bool excludeAppPaths,
BINDER_SPACE::Assembly** ppAssembly) override;

HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName,
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/binder/inc/defaultassemblybinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class DefaultAssemblyBinder final : public AssemblyBinder
public:

HRESULT BindUsingPEImage(PEImage* pPEImage,
bool excludeAppPaths,
BINDER_SPACE::Assembly** ppAssembly) override;

HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName,
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/assemblybinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AssemblyBinder
public:

HRESULT BindAssemblyByName(AssemblyNameData* pAssemblyNameData, BINDER_SPACE::Assembly** ppAssembly);
virtual HRESULT BindUsingPEImage(PEImage* pPEImage, bool excludeAppPaths, BINDER_SPACE::Assembly** ppAssembly) = 0;
virtual HRESULT BindUsingPEImage(PEImage* pPEImage, BINDER_SPACE::Assembly** ppAssembly) = 0;
virtual HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, BINDER_SPACE::Assembly** ppAssembly) = 0;

/// <summary>
Expand Down Expand Up @@ -89,7 +89,7 @@ class AssemblyBinder
{
}

SimpleNameToExpectedMVIDAndRequiringAssembly(LPCUTF8 simpleName, GUID mvid, bool compositeComponent, LPCUTF8 AssemblyRequirementName) :
SimpleNameToExpectedMVIDAndRequiringAssembly(LPCUTF8 simpleName, GUID mvid, bool compositeComponent, LPCUTF8 AssemblyRequirementName) :
SimpleName(simpleName),
Mvid(mvid),
AssemblyRequirementName(AssemblyRequirementName),
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/vm/assemblynative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p
}

/* static */
Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths)
Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage)
{
CONTRACT(Assembly*)
{
Expand All @@ -146,7 +146,7 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma

HRESULT hr = S_OK;
PTR_AppDomain pCurDomain = GetAppDomain();
hr = pBinder->BindUsingPEImage(pImage, excludeAppPaths, &pAssembly);
hr = pBinder->BindUsingPEImage(pImage, &pAssembly);

if (hr != S_OK)
{
Expand Down Expand Up @@ -250,7 +250,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl
ThrowHR(COR_E_BADIMAGEFORMAT, BFA_IJW_IN_COLLECTIBLE_ALC);
}

// Pass the stream based assembly as IL in an attempt to bind and load it
// Pass the stream-based assembly as IL in an attempt to bind and load it
Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage);
{
GCX_COOP();
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/assemblynative.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class AssemblyNative
{
public:

static Assembly* LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths = false);
static Assembly* LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage);

// static FCALLs
static FCDECL0(FC_BOOL_RET, IsTracingEnabled);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/assemblyspec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath)
if (!pILImage->CheckILFormat())
THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue());

RETURN AssemblyNative::LoadFromPEImage(AppDomain::GetCurrentDomain()->GetDefaultBinder(), pILImage, true /* excludeAppPaths */);
RETURN AssemblyNative::LoadFromPEImage(AppDomain::GetCurrentDomain()->GetDefaultBinder(), pILImage);
}

HRESULT AssemblySpec::CheckFriendAssemblyName()
Expand Down
40 changes: 40 additions & 0 deletions src/tests/Loader/binding/AppPaths/AppPaths.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
using Xunit;

public class AppPaths
{
private const string AssemblyToLoad = "AssemblyToLoad";

[Fact]
public static void DefaultALC()
{
LoadFromStream(AssemblyLoadContext.Default);
}

[Fact]
public static void CustomALC()
{
AssemblyLoadContext alc = new("alc");
LoadFromStream(alc);
}

private static void LoadFromStream(AssemblyLoadContext alc)
{
// corerun should add the app directory as the APP_PATHS property
Assert.Equal(AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar), ((string)AppContext.GetData("APP_PATHS")).TrimEnd(Path.DirectorySeparatorChar), StringComparer.OrdinalIgnoreCase);
string assemblyPath = Path.Combine(AppContext.BaseDirectory, $"{AssemblyToLoad}.dll");
byte[] assemblyBytes = File.ReadAllBytes(assemblyPath);
MemoryStream stream = new(assemblyBytes);

Assembly assembly = alc.LoadFromStream(stream);
Assert.NotNull(assembly);
Assert.Equal(AssemblyToLoad, assembly.GetName().Name);
Assert.True(string.IsNullOrEmpty(assembly.Location),
$"Assembly should be loaded from stream and have an empty Location. Actual: '{assembly.Location}'");
}
}
9 changes: 9 additions & 0 deletions src/tests/Loader/binding/AppPaths/AppPaths.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Compile Include="AppPaths.cs" />
</ItemGroup>
<ItemGroup>
<!-- <ProjectReference Include="$(TestLibraryProjectPath)" /> -->
<ProjectReference Include="AssemblyToLoad.csproj" />
</ItemGroup>
</Project>
6 changes: 6 additions & 0 deletions src/tests/Loader/binding/AppPaths/AssemblyToLoad.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace AssemblyToLoad
{
}
8 changes: 8 additions & 0 deletions src/tests/Loader/binding/AppPaths/AssemblyToLoad.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyToLoad.cs" />
</ItemGroup>
</Project>
Loading