[Mono-bugs] [Bug 73349][Cri] New - Enumerations and ValueTypes built with Emit makes assembly crash when loading (invalid assembly!)

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Fri, 4 Mar 2005 11:11:46 -0500 (EST)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by martin.tapp@cae.com.

http://bugzilla.ximian.com/show_bug.cgi?id=73349

--- shadow/73349	2005-03-04 11:11:46.000000000 -0500
+++ shadow/73349.tmp.11324	2005-03-04 11:11:46.000000000 -0500
@@ -0,0 +1,155 @@
+Bug#: 73349
+Product: Mono: Class Libraries
+Version: 1.1
+OS: Red Hat 9.0
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Critical
+Component: CORLIB
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: martin.tapp@cae.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Enumerations and ValueTypes built with Emit makes assembly crash when loading (invalid assembly!)
+
+Description of Problem:
+When using reflection to create enumerations and value types, assembly 
+fails to be a valid assembly when saved!  Enumerations make this happen, 
+but not the value types.
+
+
+Steps to reproduce the problem:
+Using System.Collections:
+Using Reflection:
+Using Reflection.Emit:
+
+public interface IMyValueType {}
+
+AssemblyName wAsmName = new AssemblyName();
+wAsmName.Name = "MyAssembly";
+
+string wPath = "/Some Path(1)";
+string wAssemblyDll = wPath + "/MyAssembly.dll";
+
+AssemblyBuilder wAsmBuilder = 
+AppDomain.CurrentDomain.DefineDynamicAssembly
+(wAsmName,AssemblyBuilderAccess.RunAndSave,wPath);
+
+ModuleBuilder wModuleBuilder = wAsmBuilder.DefineDynamicModule
+(wAssemblyDll,wAssemblyDll,false);
+
+IDictionary wEnums = new SortedList();
+// Create enumeration - comment out to test
+/*
+Type wEnumType = typeof(uint);
+EnumBuilder wEnumBuilder = wModuleBuilder.DefineEnum
+("MyNamespace1.MyNamespace2.MyEnum",TypeAttributes.Public,wEnumType);
+
+wEnumBuilder.DefineLiteral("SomeLiteral1",Convert.ChangeType
+(1234,wEnumType));
+wEnumBuilder.DefineLiteral("SomeLiteral2",Convert.ChangeType
+(5678,wEnumType));
+
+// Note: on Windows, the wEnumBuilder can be used after the type is 
+created, in mono on Linux RH9 it crashes
+Type wEnumerationType = wEnumBuilder.CreateType();
+wEnums[wEnumBuilder.Name.ToLower()] = wEnumBuilder;
+// Need to to this instead:
+//wEnums[wEnumerationType.Name.ToLower()] = wEnumerationType;
+//*/
+
+
+// Create complex data type - comment out to test
+/*
+Type[] wInterfaces = { typeof(IMyValueType) };
+TypeBuilder wValueType1 = wModuleBuilder.DefineType
+("MyNamespace1.MyNamespace2.MyValueType1",TypeAttributes.Public|TypeAttribu
+tes.Class|TypeAttributes.SequentialLayout|TypeAttributes.Serializable,typeo
+f(ValueType),wInterfaces);
+
+DefineField(wValueType1,"MyField1",typeof(int));
+DefineField(wValueType1,"MyField2",typeof(float));
+
+wValueType1.CreateType();
+
+
+TypeBuilder wValueType2 = wModuleBuilder.DefineType
+("MyNamespace1.MyNamespace2.MyValueType2",TypeAttributes.Public|TypeAttribu
+tes.Class|TypeAttributes.SequentialLayout|TypeAttributes.Serializable,typeo
+f(ValueType),wInterfaces);
+
+DefineField(wValueType2,"MyField1",wValueType1);
+DefineField(wValueType1,"MyField2",typeof(float));
+
+wValueType2.CreateType();
+//*/
+
+wAsmBuilder.Save(wAssemblyDll);
+
+Assembly wAssembly = AppDomain.CurrentDomain.Load
+(AssemblyName.GetAssemblyName(wAssemblyDll));
+
+public void DefinedField(TypeBuilder iTypeBuilder,string iAttrName,Type 
+iAttrType)
+{
+  string       wFieldName = string.Concat("_",iAttrName);
+  FieldBuilder wField     = iTypeBuilder.DefineField
+(wFieldName,iAttrType,FieldAttributes.Private);
+
+  Type[]          wArgs     = { iAttrType };
+  PropertyBuilder wProperty = iTypeBuilder.DefineProperty
+(iAttrName,PropertyAttributes.None,iAttrType,Type.EmptyTypes);
+
+  // "get" property method
+  string        wAttrMethodName = string.Concat("get_",iAttrName);
+  MethodBuilder wGetMethod      = iTypeBuilder.DefineMethod
+(wAttrMethodName,MethodAttributes.Public,CallingConventions.HasThis,iAttrTy
+pe,Type.EmptyTypes);
+  ILGenerator   wGetIL          = wGetMethod.GetILGenerator();
+  // return _mField;
+  wGetIL.Emit(OpCodes.Ldarg_0);
+  wGetIL.Emit(OpCodes.Ldfld,wField);
+  wGetIL.Emit(OpCodes.Ret);
+
+  // "set" property method
+  wAttrMethodName          = string.Concat("set_",iAttrName);
+  MethodBuilder wSetMethod = iTypeBuilder.DefineMethod
+(wAttrMethodName,MethodAttributes.Public,CallingConventions.HasThis,null,wA
+rgs);
+  ILGenerator   wSetIL     = wSetMethod.GetILGenerator();
+  // _mField = iField;
+  wSetIL.Emit(OpCodes.Ldarg_0);
+  wSetIL.Emit(OpCodes.Ldarg_1);
+  wSetIL.Emit(OpCodes.Stfld,wField);
+  wSetIL.Emit(OpCodes.Ret);
+
+  // Map the get and set methods to the property get and set respectively
+  wProperty.SetGetMethod(wGetMethod);
+  wProperty.SetSetMethod(wSetMethod);
+}
+
+Actual Results:
+If only value types are defined, assembly is valid but throws when loading 
+the value type (Cannot load type exception).  On Windows, the same 
+assembly works fine (compiled with mono).
+
+If only enumerations are defined, assembly is invalid and cannot be read 
+at all (** ERROR **: file class.c: line 1742 (mono_class_setup_parent): 
+should not be reached aborting... Aborted). Even opening the assembly with 
+ILDASM or .NET Reflector makes these tools crash!
+
+
+Expected Results:
+Works fine on Windows.
+
+How often does this happen? 
+Always
+
+Additional Information:
+The Value type problem might be related to the fact that once CreateType() 
+is called, the builder cannot be accessed on mono RH9, but on Windows it 
+can.