From 5e68b1611a96f4b208c6d7cd6b923582b6231a76 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Mon, 27 Sep 2021 14:35:55 -0700 Subject: [PATCH] fixed FileLoadException when trying to do clr.AddReference('/full/lib/path.dll') Before trying to load an assembly by its full path we were trying to call `Assembly.Load` on it. `Assembly.Load` interprets its argument as a valid `AssemblyName`. However full paths are not valid assembly names, so that call would throw `FileLoadException`, which we did not handle. reported in https://github.com/pythonnet/pythonnet/commit/9d5f57973bafb9086bb7664547abbd73c9fabc3c#commitcomment-57061082 Related: https://github.com/pythonnet/pythonnet/issues/1514 --- src/embed_tests/pyimport.cs | 14 ++++++++++++-- src/runtime/assemblymanager.cs | 25 +++++++++++++++---------- src/runtime/moduleobject.cs | 4 ++-- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/embed_tests/pyimport.cs b/src/embed_tests/pyimport.cs index 26dc91ff7..f590ada4c 100644 --- a/src/embed_tests/pyimport.cs +++ b/src/embed_tests/pyimport.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using System.Runtime.InteropServices; + using NUnit.Framework; using Python.Runtime; @@ -83,10 +85,18 @@ public void TestCastGlobalVar() public void BadAssembly() { string path; - if (Python.Runtime.Runtime.IsWindows) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { path = @"C:\Windows\System32\kernel32.dll"; } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + path = "/usr/lib/libc.dylib"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + path = "/usr/lib/locale/locale-archive"; + } else { Assert.Pass("TODO: add bad assembly location for other platforms"); @@ -98,7 +108,7 @@ import clr clr.AddReference('{path}') "; - Assert.Throws(() => PythonEngine.Exec(code)); + Assert.Throws(() => PythonEngine.Exec(code)); } } } diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index 74720e1a6..2bc27bf4d 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -121,6 +121,18 @@ private static Assembly ResolveHandler(object ob, ResolveEventArgs args) return LoadAssemblyPath(name.Name); } + internal static AssemblyName? TryParseAssemblyName(string name) + { + try + { + return new AssemblyName(name); + } + catch (FileLoadException) + { + return null; + } + } + /// /// We __really__ want to avoid using Python objects or APIs when @@ -208,18 +220,11 @@ static IEnumerable FindAssemblyCandidates(string name) /// /// Loads an assembly from the application directory or the GAC - /// given a simple assembly name. Returns the assembly if loaded. + /// given its name. Returns the assembly if loaded. /// - public static Assembly LoadAssembly(string name) + public static Assembly LoadAssembly(AssemblyName name) { - try - { - return Assembly.Load(name); - } - catch (FileNotFoundException) - { - return null; - } + return Assembly.Load(name); } diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index 569d2e00c..2fa007604 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -516,9 +516,9 @@ public static Assembly AddReference(string name) { assembly = AssemblyManager.LoadAssemblyPath(name); } - if (assembly == null) + if (assembly == null && AssemblyManager.TryParseAssemblyName(name) is { } parsedName) { - assembly = AssemblyManager.LoadAssembly(name); + assembly = AssemblyManager.LoadAssembly(parsedName); } if (assembly == null) {