Fix crash when loading C# assembly from non-ASNSI path

#1439
This commit is contained in:
Wojtek Figat
2023-09-25 16:30:24 +02:00
parent cfd53eea60
commit 96b6313acb
2 changed files with 38 additions and 31 deletions

View File

@@ -851,39 +851,46 @@ namespace FlaxEngine.Interop
*assemblyFullName = NativeAllocStringAnsi(flaxEngineAssembly.FullName); *assemblyFullName = NativeAllocStringAnsi(flaxEngineAssembly.FullName);
return GetAssemblyHandle(flaxEngineAssembly); return GetAssemblyHandle(flaxEngineAssembly);
} }
try
{
string assemblyPath = Marshal.PtrToStringAnsi(assemblyPathPtr);
string assemblyPath = Marshal.PtrToStringAnsi(assemblyPathPtr); Assembly assembly;
Assembly assembly;
#if FLAX_EDITOR #if FLAX_EDITOR
// Load assembly from loaded bytes to prevent file locking in Editor // Load assembly from loaded bytes to prevent file locking in Editor
var assemblyBytes = File.ReadAllBytes(assemblyPath); var assemblyBytes = File.ReadAllBytes(assemblyPath);
using MemoryStream stream = new MemoryStream(assemblyBytes); using MemoryStream stream = new MemoryStream(assemblyBytes);
var pdbPath = Path.ChangeExtension(assemblyPath, "pdb"); var pdbPath = Path.ChangeExtension(assemblyPath, "pdb");
if (File.Exists(pdbPath)) if (File.Exists(pdbPath))
{ {
// Load including debug symbols // Load including debug symbols
using FileStream pdbStream = new FileStream(Path.ChangeExtension(assemblyPath, "pdb"), FileMode.Open); using FileStream pdbStream = new FileStream(Path.ChangeExtension(assemblyPath, "pdb"), FileMode.Open);
assembly = scriptingAssemblyLoadContext.LoadFromStream(stream, pdbStream); assembly = scriptingAssemblyLoadContext.LoadFromStream(stream, pdbStream);
} }
else else
{ {
assembly = scriptingAssemblyLoadContext.LoadFromStream(stream); assembly = scriptingAssemblyLoadContext.LoadFromStream(stream);
} }
#else #else
// Load assembly from file // Load assembly from file
assembly = scriptingAssemblyLoadContext.LoadFromAssemblyPath(assemblyPath); assembly = scriptingAssemblyLoadContext.LoadFromAssemblyPath(assemblyPath);
#endif #endif
if (assembly == null) if (assembly == null)
return new ManagedHandle(); return new ManagedHandle();
NativeLibrary.SetDllImportResolver(assembly, NativeLibraryImportResolver); NativeLibrary.SetDllImportResolver(assembly, NativeLibraryImportResolver);
// Assemblies loaded via streams have no Location: https://github.com/dotnet/runtime/issues/12822 // Assemblies loaded via streams have no Location: https://github.com/dotnet/runtime/issues/12822
AssemblyLocations.Add(assembly.FullName, assemblyPath); AssemblyLocations.Add(assembly.FullName, assemblyPath);
*assemblyName = NativeAllocStringAnsi(assembly.GetName().Name); *assemblyName = NativeAllocStringAnsi(assembly.GetName().Name);
*assemblyFullName = NativeAllocStringAnsi(assembly.FullName); *assemblyFullName = NativeAllocStringAnsi(assembly.FullName);
return GetAssemblyHandle(assembly); return GetAssemblyHandle(assembly);
}
catch (Exception ex)
{
Debug.LogException(ex);
}
return new ManagedHandle();
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]

View File

@@ -704,12 +704,10 @@ bool MAssembly::LoadImage(const String& assemblyPath, const StringView& nativePa
// TODO: Use new hostfxr delegate load_assembly_bytes? (.NET 8+) // TODO: Use new hostfxr delegate load_assembly_bytes? (.NET 8+)
// Open .Net assembly // Open .Net assembly
const StringAnsi assemblyPathAnsi = assemblyPath.ToStringAnsi(); const StringAnsi assemblyPathAnsi = assemblyPath.ToStringAnsi();
const char* name; const char* name = nullptr;
const char* fullname; const char* fullname = nullptr;
static void* LoadAssemblyImagePtr = GetStaticMethodPointer(TEXT("LoadAssemblyImage")); static void* LoadAssemblyImagePtr = GetStaticMethodPointer(TEXT("LoadAssemblyImage"));
_handle = CallStaticMethod<void*, const char*, const char**, const char**>(LoadAssemblyImagePtr, assemblyPathAnsi.Get(), &name, &fullname); _handle = CallStaticMethod<void*, const char*, const char**, const char**>(LoadAssemblyImagePtr, assemblyPathAnsi.Get(), &name, &fullname);
_name = name;
_fullname = fullname;
MCore::GC::FreeMemory((void*)name); MCore::GC::FreeMemory((void*)name);
MCore::GC::FreeMemory((void*)fullname); MCore::GC::FreeMemory((void*)fullname);
if (_handle == nullptr) if (_handle == nullptr)
@@ -717,6 +715,8 @@ bool MAssembly::LoadImage(const String& assemblyPath, const StringView& nativePa
Log::CLRInnerException(TEXT(".NET assembly image is invalid at ") + assemblyPath); Log::CLRInnerException(TEXT(".NET assembly image is invalid at ") + assemblyPath);
return true; return true;
} }
_name = name;
_fullname = fullname;
CachedAssemblyHandles.Add(_handle, this); CachedAssemblyHandles.Add(_handle, this);
// Provide new path of hot-reloaded native library path for managed DllImport // Provide new path of hot-reloaded native library path for managed DllImport