Skip to content

Calling GetName() on a System.Reflection.Assembly that is loaded from a byte stream will throw exception in Japanese locale #20968

@MerlinVR

Description

@MerlinVR

Steps to Reproduce

  1. Set system locale to Japanese & restart system to apply locale, the locale settings I'm referring to just to be clear since I don't mean having the Japanese IME setup: (https://www.java.com/en/download/help/locale.html)
  2. Make a directory with a path that includes Japanese characters which will contain the executable at some level. In my tests the exact path to the compiled exe was C:\Users\userドキュメント\Unity Projects\MonoTest\MonoTest\bin\Debug\MonoTest.exe
  3. In a C# console project, Compile and Emit an assembly at runtime, using Roslyn in this case. See attached files for example project. Load the assembly via System.Reflection.Assembly.Load(), and then call GetName() on the loaded assembly.
  4. Compile executable, in this case it was compiled in VS2017
  5. Make sure the Mono bin directory is added to the System PATH
  6. Open some terminal app, in this case I used Powershell.
  7. IMPORTANT: cd the working directory to the same directory as the executable, in my case: cd "C:\Users\userドキュメント\Unity Projects\MonoTest\MonoTest\bin\Debug"
  8. Execute built exe on mono, in my case: mono "C:\Users\userドキュメント\Unity Projects\MonoTest\MonoTest\bin\Debug\MonoTest.exe"
  9. Receive exception inside icall System.Reflection.RuntimeAssembly.get_code_base()

To run example, install dependencies listed in packages.config via nuget and compile Debug build in VS2017, presumably other build environments will work as well. The program is contained in Program.cs. The built exe is also included in the bin directory

MonoTest.zip

Current Behavior

Will throw an exception System.ExecutionEngineException: String conversion error: Illegal byte sequence encounted in the input. when GetName() is called on loaded assembly. Full stack trace included below

Expected Behavior

Prints the assembly name without throwing. The exact expected output of the program to the console is:

Hello!
MyTestAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Success!

Also tested by just running the exe directly to use the .NET runtime and it works as expected:
image
image

Details

Mono actually works as expected if your working directory does not contain Japanese characters. Just executing the program from the Users root dir prints the expected output without errors
image

It is only when you make the working directory contain Japanese characters that the runtime-created assembly with no connection to the file system will somehow break:
image

This seemed odd since other assemblies that aren't runtime loaded work fine. So I tried saving the assembly to the same directory as the exe and then loading it from the file directly using Assembly.LoadFrom() and supplying the path to the assembly that I saved to disk as a .dll. This also threw the same exception, so it didn't seem like just loading the assembly from the disk works. Then why can most other system assemblies load properly and have GetName() called on them? At least in part, it seems like it's because most of the assemblies are actually stored in some directory without Japanese characters. If I saved the generated assembly to a directory outside the project in some directory that doesn't include Japanese characters, it loaded correctly without issue.

The reason I don't use just mono MonoTest.exe here is because mono throws a fit for no reason, and I cannot find an encoding for the MONO_EXTERNAL_ENCODINGS that works. utf8, utf32, all naming variations of shift-jis throw the same error, and utf16 just hangs the program indefinitely:
image

On which platforms did you notice this

[ ] macOS
[ ] Linux
[x] Windows

Version Used:
6.12.0, this issue was originally noticed in Unity 2018.4.20f1 and then reproduced in the latest stable version of Mono.

Stacktrace

Unhandled Exception:
System.ExecutionEngineException: String conversion error: Illegal byte sequence encounted in the input.
  at (wrapper managed-to-native) System.Reflection.RuntimeAssembly.get_code_base(System.Reflection.Assembly,bool)
  at System.Reflection.RuntimeAssembly.GetCodeBase (System.Reflection.Assembly a, System.Boolean escaped) [0x00000] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.RuntimeAssembly.get_CodeBase () [0x00000] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.AssemblyName.Create (System.Reflection.Assembly assembly, System.Boolean fillCodebase) [0x00010] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.RuntimeAssembly.GetName (System.Boolean copiedName) [0x0000e] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.Assembly.GetName () [0x00000] in <32116eccb94d4ed685ca661d98e36637>:0
  at MonoTest.Program.Main (System.String[] args) [0x00177] in <b10c1804a8eb477aa9eef64e391e55b9>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ExecutionEngineException: String conversion error: Illegal byte sequence encounted in the input.
  at (wrapper managed-to-native) System.Reflection.RuntimeAssembly.get_code_base(System.Reflection.Assembly,bool)
  at System.Reflection.RuntimeAssembly.GetCodeBase (System.Reflection.Assembly a, System.Boolean escaped) [0x00000] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.RuntimeAssembly.get_CodeBase () [0x00000] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.AssemblyName.Create (System.Reflection.Assembly assembly, System.Boolean fillCodebase) [0x00010] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.RuntimeAssembly.GetName (System.Boolean copiedName) [0x0000e] in <32116eccb94d4ed685ca661d98e36637>:0
  at System.Reflection.Assembly.GetName () [0x00000] in <32116eccb94d4ed685ca661d98e36637>:0
  at MonoTest.Program.Main (System.String[] args) [0x00177] in <b10c1804a8eb477aa9eef64e391e55b9>:0

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions