Greetings,
I just wanted to know if anyone else has noticed that ilasm incorrectly encodes type names on CustomAttributes. Let's give an example:
.assembly SerializationError { .ver 1:0:0:0 .hash algorithm 0x00008004 } .module SerializationError.exe .subsystem 0x0003 // MVID: {4CC49ABD-FEB2-4D33-8FE4-A9FED179B4EA} // Target Runtime Version: v4.0.30319 // Platform Target : x86 .assembly extern mscorlib { .ver 4:0:0:0 .publickeytoken = (B7 7A 5C 56 19 34 E0 89) } .namespace SerializationError { .class private auto ansi beforefieldinit SerializationTestAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = { int32(0x7fff) } .method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Type target) cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]System.Attribute::.ctor() L_0006: nop L_0007: nop L_0008: ldarg.0 L_0009: ldarg.1 L_000a: stfld class [mscorlib]System.Type SerializationError.SerializationTestAttribute::target L_000f: nop L_0010: ret } .property instance class [mscorlib]System.Type Target() { .get instance class [mscorlib]System.Type SerializationError.SerializationTestAttribute::get_Target() } .method public hidebysig specialname instance class [mscorlib]System.Type get_Target() cil managed { // Code size 12 (0xc) .maxstack 1 .locals init ([0] class [mscorlib]System.Type CS$1$0000) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldfld class [mscorlib]System.Type SerializationError.SerializationTestAttribute::target IL_0007: stloc.0 IL_0008: br.s IL_000a IL_000a: ldloc.0 IL_000b: ret } // end of method SerializationTestAttribute::get_Target .field private class [mscorlib]System.Type target } .class private auto ansi beforefieldinit 'Serialization+Test+Class' extends [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]System.Object::.ctor() L_0006: ret } } .class private abstract auto ansi sealed beforefieldinit SerializationTestProgram extends [mscorlib]System.Object { // .custom instance void SerializationError.SerializationTestAttribute::.ctor(class [mscorlib]System.Type) = { type(SerializationError.'Serialization+Test+Class') } /* * * The above line generates the following metadata entry: * .custom instance void SerializationError.SerializationTestAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 2B 53 65 72 69 61 6C 69 7A 61 74 69 6F 6E // ..+Serialization * 45 72 72 6F 72 2E 53 65 72 69 61 6C 69 7A 61 74 // Error.Serializat * 69 6F 6E 2B 54 65 73 74 2B 43 6C 61 73 73 00 00 ) // ion+Test+Class.. * The proper value is shown below: * */ .custom instance void SerializationError.SerializationTestAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 2D 53 65 72 69 61 6C 69 7A 61 74 69 6F 6E // ..-Serialization 45 72 72 6F 72 2E 53 65 72 69 61 6C 69 7A 61 74 // Error.Serializat 69 6F 6E 5C 2B 54 65 73 74 5C 2B 43 6C 61 73 73 00 00 ) // ion\+Test\+Class.. .method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 3 .locals init ( [0] class [mscorlib]System.Type 'type', [1] class SerializationError.SerializationTestAttribute attribute) L_0000: nop L_0001: ldtoken SerializationError.SerializationTestProgram L_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) L_000b: stloc.0 L_000c: ldloc.0 L_000d: ldtoken SerializationError.SerializationTestAttribute L_0012: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) L_0017: ldc.i4.1 L_0018: callvirt instance object[] [mscorlib]System.Reflection.MemberInfo::GetCustomAttributes(class [mscorlib]System.Type, bool) L_001d: ldc.i4.0 L_001e: ldelem.ref L_001f: castclass SerializationError.SerializationTestAttribute L_0024: stloc.1 L_0025: ldloc.1 L_0026: callvirt instance class [mscorlib]System.Type SerializationError.SerializationTestAttribute::get_Target() L_002b: call void [mscorlib]System.Console::WriteLine(object) L_0030: nop L_0031: ret } } }
The type SerializationError.'Serialization+Test+Class'
when used within type() on a custom attribute, accepting a type, yields a serialized string which doesn't escape the '+' characters within the name, when reflection attempts
to parse the value from the custom attribute's SerString, a type load exception results, because it's looking for nested types.