Invalid Metadata generated when changing visibility of nested Type #83

Closed
opened 2011-11-01 10:44:42 -05:00 by JohannesRudolph · 2 comments
JohannesRudolph commented 2011-11-01 10:44:42 -05:00 (Migrated from github.com)

Consdering the following code (global namespace) compiled into an assembly:

public class Base
{
public void ProtectableMethod()
{
    new Nested();
}
private class Nested
{
    public Nested() { }
}
}

When reading the assembly, changing the visibility of Nested to "public" via:

    var ad = AssemblyDefinition.ReadAssembly( typeof( Base ).Assembly.Location );
    var @base = ad.MainModule.GetType( "Base" );
    var nested = @base.NestedTypes.Single();
    nested.IsPublic = true;

writing out the assembly and attempting to load it, a BadImageFormatException with the following message is generated: "TypeDef is not marked Nested but has an enclosing type."

Roundtripping the assembly without touching the visibility of the Nested type does not yield this error. Tools such as ILSpy have their problems with the generated assembly (Nested is shown twice, once as a namespace-level class and once as nested). I assume its an error in the generation of metadata.

The full code used to reproduce the issue (Compile as C# console app, add cecil via nuget):

using System;
using System.Collections.Generic;
using Mono.Cecil;
using System.Linq;
using System.Reflection;

public class Base
{
    public void ProtectableMethod()
    {
        new Nested();
    }
    private class Nested
    {
        public Nested() { }
    }
}

class Program
{
    const string AssemblyDumpPath = @"C:\tmp\repro.dll";

    static void Main( string[] args )
    {
        var ad = AssemblyDefinition.ReadAssembly( typeof( Base ).Assembly.Location );

        // change the visibility of Nested to public
        var @base = ad.MainModule.GetType( "Base" );
        var nested = @base.NestedTypes.Single();
        nested.IsPublic = true;

        // change the assembly name so we can reload the assembly into the same appdomain
        ad.Name.Name = "NewAssemblyName";

        ad.Write( AssemblyDumpPath );

        try
        {
            var asm = Assembly.LoadFrom( AssemblyDumpPath );
            asm.GetType( "Base+Nested" ); // trigger the exception

            Console.WriteLine( "Happy days!" );
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        Console.ReadLine();
    }
}
Consdering the following code (global namespace) compiled into an assembly: ``` public class Base { public void ProtectableMethod() { new Nested(); } private class Nested { public Nested() { } } } ``` When reading the assembly, changing the visibility of Nested to "public" via: ``` var ad = AssemblyDefinition.ReadAssembly( typeof( Base ).Assembly.Location ); var @base = ad.MainModule.GetType( "Base" ); var nested = @base.NestedTypes.Single(); nested.IsPublic = true; ``` writing out the assembly and attempting to load it, a BadImageFormatException with the following message is generated: "TypeDef is not marked Nested but has an enclosing type." Roundtripping the assembly without touching the visibility of the Nested type does not yield this error. Tools such as ILSpy have their problems with the generated assembly (Nested is shown twice, once as a namespace-level class and once as nested). I assume its an error in the generation of metadata. The full code used to reproduce the issue (Compile as C# console app, add cecil via nuget): ``` using System; using System.Collections.Generic; using Mono.Cecil; using System.Linq; using System.Reflection; public class Base { public void ProtectableMethod() { new Nested(); } private class Nested { public Nested() { } } } class Program { const string AssemblyDumpPath = @"C:\tmp\repro.dll"; static void Main( string[] args ) { var ad = AssemblyDefinition.ReadAssembly( typeof( Base ).Assembly.Location ); // change the visibility of Nested to public var @base = ad.MainModule.GetType( "Base" ); var nested = @base.NestedTypes.Single(); nested.IsPublic = true; // change the assembly name so we can reload the assembly into the same appdomain ad.Name.Name = "NewAssemblyName"; ad.Write( AssemblyDumpPath ); try { var asm = Assembly.LoadFrom( AssemblyDumpPath ); asm.GetType( "Base+Nested" ); // trigger the exception Console.WriteLine( "Happy days!" ); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.ReadLine(); } } ```
JohannesRudolph commented 2011-11-01 11:50:20 -05:00 (Migrated from github.com)

Can be closed: One needs to use IsNestedPublic vs. IsPublic.

Can be closed: One needs to use IsNestedPublic vs. IsPublic.
jbevain commented 2011-11-01 13:21:23 -05:00 (Migrated from github.com)

:)

:)
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-jbevain/cecil#83
No description provided.