Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullReferenceException when trying to resolve ModuleReference members #725

Closed
AnakinRaW opened this issue Mar 11, 2021 · 6 comments
Closed

Comments

@AnakinRaW
Copy link
Contributor

AnakinRaW commented Mar 11, 2021

The testcode i used is copied from https://docs.microsoft.com/en-us/dotnet/framework/app-domains/build-multifile-assembly

Scenario:

I compiled the tutorial from the link above.
This yields the following files: myAssembly.exe Client.netmodule and Stringer.netmodule
I'm trying to resolve as many Reference members into their matching Definitions (e.g. TypeReference --> TypeDefinition)

Error Description:

i'm running the following code:

 var appA = AssemblyDefinition.ReadAssembly("myAssembly.exe");

// Get all types from module 'Client.netmodule'
foreach (var t in modules_A.Skip(1).First().Types)
{
    if (t.Name == "<Module>")
        continue;

    // IL_0013: callvirt System.Void myStringer.Stringer::StringerMethod()
    var callInst = t.Methods.First(m => m.Name.Equals("Main")).Body.Instructions[7];

    if (callInst.Operand is not MethodReference methodReference)
        continue;

    // Type Name: myStringer.Stringer
    // TypeRef Scope: Stringer.netmodule ScopeType:ModuleReference
    var methodTypeRef = methodReference.DeclaringType;

    var methodTypeDef = methodTypeRef.Resolve();
}

The line var methodTypeDef = methodTypeRef.Resolve(); fails with an NRE becuase:

  • methodTypeRef 's module is 'Client.netmodule'
  • The ModuleDefinition of 'Client.netmodule' has no Assembly (null). According to ECMA this is valid.
  • The MetadataResolver implementation is as follows: var modules = type.Module.Assembly.Modules; As you see it assumes, a ModuleDefinition always has an Assembly assigned to it.

Solutions

I see a couple of solutions here.

  1. Check whether the module has an assembly
    a. return null in that case, indicating that it was impossible to find a proper TypeDefinition
    b. Have some heuristic-based logic which tries to find a ModuleDefinition which matches the ModuleReferenc's name. Either lookup the assembly resolver's lookup directories for such a module or try on some cached ModuleDefinitions. Return null when no module was found or no module contained to TypeDefinition of the searched TypeReference. Or return the TypeDefinition if found. I think it should be noted however that this approach might return a wrong TypeDefinition if the wrong module matched.
  2. Same as for 1. But instead of returning null, throw a proper exception.

There are probably more and smarter solutions but I think that's up to you to decide @jbevain

@jbevain
Copy link
Owner

jbevain commented Mar 12, 2021

Hey, thanks for filing this and investigating.

Could you zip the binaries and attach them to the issue? Thank you!

@AnakinRaW AnakinRaW changed the title NullReferenceException when trying to resolve ModuleReference memebers NullReferenceException when trying to resolve ModuleReference members Mar 12, 2021
@jbevain
Copy link
Owner

jbevain commented Mar 13, 2021

Could you zip the binaries and attach them to the issue? Thank you!

Or better yet, start a PR with a failing test!

@AnakinRaW
Copy link
Contributor Author

Failed test added in #730

@jbevain
Copy link
Owner

jbevain commented Mar 15, 2021

Thank you, I'll have a look!

(Using netmodules is not a good idea they're just a source of pain on earth)

@AnakinRaW
Copy link
Contributor Author

Yeah, i'm aware of it. Easily the much flawed design choice of the ECMA Spec, but I'm developing tools tools which need to handle the full ECMA and that sadly includes multi-module assemblies and shared modules.

@jbevain
Copy link
Owner

jbevain commented Apr 23, 2021

Fixed by #730

@jbevain jbevain closed this as completed Apr 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants