From: Rodrigo Kumpera Date: Mon, 25 Sep 2017 22:35:41 +0000 (-0700) Subject: [runtime] Handle RuntimeWrappedException and dynamic methods using a SRE as module... X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=02155d6cebd7e06f7339c91efb343fbaaf4f36a7 [runtime] Handle RuntimeWrappedException and dynamic methods using a SRE as module. Fixes #59334 A DynamicMethod can be placed in a SRE module and it must respect any RuntimeCompatibilityAttribute set on that assembly. We do that by updating the runtime side list of cattr in the AssemblyBuilder when a RuntimeCompatibilityAttribute is set using SetCustomAttribute. --- diff --git a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs index 9312f1da9fe..9c642ffa006 100644 --- a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs @@ -257,6 +257,9 @@ namespace System.Reflection.Emit [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void basic_init (AssemblyBuilder ab); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + static extern void UpdateNativeCustomAttributes (AssemblyBuilder ab); + /* Keep this in sync with codegen.cs in mcs */ private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800; @@ -949,6 +952,12 @@ namespace System.Reflection.Emit cattrs = new CustomAttributeBuilder [1]; cattrs [0] = customBuilder; } + + /* + Only update the native list of custom attributes if we're adding one that is known to change dynamic execution behavior. + */ + if (customBuilder.Ctor != null && customBuilder.Ctor.DeclaringType == typeof (System.Runtime.CompilerServices.RuntimeCompatibilityAttribute)) + UpdateNativeCustomAttributes (this); } [ComVisible (true)] diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs index fcf6284a00e..f8c898d2f00 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/DynamicMethodTest.cs @@ -610,6 +610,102 @@ namespace MonoTests.System.Reflection.Emit invoke (444); } + static Func EmitDelegate (DynamicMethod dm) { + ILGenerator il = dm.GetILGenerator (); + var ret_val = il.DeclareLocal (typeof (int)); + var leave_label = il.DefineLabel (); + + //ret = 1; + il.Emit (OpCodes.Ldc_I4, 1); + il.Emit (OpCodes.Stloc, ret_val); + + // try { + il.BeginExceptionBlock (); + // throw "hello"; + il.Emit (OpCodes.Ldstr, "hello"); + il.Emit (OpCodes.Throw, typeof (string)); + // ret = 2 + il.Emit (OpCodes.Ldc_I4, 2); + il.Emit (OpCodes.Stloc, ret_val); + // } + il.Emit (OpCodes.Leave, leave_label); + //catch (string) + il.BeginCatchBlock (typeof (string)); + il.Emit (OpCodes.Pop); + // ret = 3 + il.Emit (OpCodes.Ldc_I4, 3); + il.Emit (OpCodes.Stloc, ret_val); + //} + il.Emit (OpCodes.Leave, leave_label); + il.EndExceptionBlock (); + + il.MarkLabel (leave_label); + //return ret; + il.Emit (OpCodes.Ldloc, ret_val); + il.Emit (OpCodes.Ret); + + var dele = (Func)dm.CreateDelegate (typeof (Func)); + return dele; + } + + [Test] //see bxc #59334 + public void ExceptionWrapping () + { + AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ehatevfheiw"), AssemblyBuilderAccess.Run); + AssemblyBuilder ab2 = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ddf4234"), AssemblyBuilderAccess.Run); + CustomAttributeBuilder cab = new CustomAttributeBuilder ( + typeof (RuntimeCompatibilityAttribute).GetConstructor (new Type [0]), + new object [0], + new PropertyInfo[] { typeof (RuntimeCompatibilityAttribute).GetProperty ("WrapNonExceptionThrows") }, + new object[] { true }); + ab2.SetCustomAttribute (cab); + + AssemblyBuilder ab3 = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("frfhfher"), AssemblyBuilderAccess.Run); + //1 NamedArg. Property name: WrapNonExceptionThrows value: true (0x01) + byte[] blob = new byte[] { 0x01, 0x00, 0x01, 0x00, 0x54, 0x02, 0x16, 0x57, 0x72, 0x61, 0x70, 0x4E, 0x6F, 0x6E, 0x45, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x54, 0x68, 0x72, 0x6F, 0x77, 0x73, 0x01 }; + ab3.SetCustomAttribute (typeof (RuntimeCompatibilityAttribute).GetConstructor (new Type [0]), blob); + + DynamicMethod invoke_no_module = new DynamicMethod("throw_1", typeof (int), new Type [0]); + DynamicMethod invoke_with_module = new DynamicMethod("throw_2", typeof (int), new Type [0], typeof (DynamicMethodTest).Module); + DynamicMethod invoke_with_ab = new DynamicMethod("throw_3", typeof (int), new Type [0], ab.ManifestModule); + DynamicMethod invoke_with_ab2 = new DynamicMethod("throw_4", typeof (int), new Type [0], ab2.ManifestModule); + DynamicMethod invoke_with_ab3 = new DynamicMethod("throw_5", typeof (int), new Type [0], ab3.ManifestModule); + + int result = 0; + try { + int res = EmitDelegate (invoke_no_module)(); + Assert.AreEqual (3, res, "invoke_no_module bad return value"); + } catch (RuntimeWrappedException e) { + Assert.Fail ("invoke_no_module threw RWE"); + } + + try { + int res = EmitDelegate (invoke_with_module)(); + Assert.Fail ("invoke_with_module did not throw RWE"); + } catch (RuntimeWrappedException e) { + } + + try { + int res = EmitDelegate (invoke_with_ab)(); + Assert.AreEqual (3, res, "invoke_with_ab bad return value"); + } catch (RuntimeWrappedException e) { + Assert.Fail ("invoke_with_ab threw RWE"); + } + + try { + int res = EmitDelegate (invoke_with_ab2)(); + Assert.Fail ("invoke_with_ab2 did not throw RWE"); + } catch (RuntimeWrappedException e) { + } + + try { + int res = EmitDelegate (invoke_with_ab3)(); + Assert.Fail ("invoke_with_a3 did not throw RWE"); + } catch (RuntimeWrappedException e) { + } + } + #if !MONODROID // RUNTIME: crash [Test] diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 28615d8c1a9..47fbefe2cda 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -535,7 +535,8 @@ ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token) ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1) ICALL(CATTR_DATA_1, "ResolveArgumentsInternal", ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal) -ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_2) +ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_1) +HANDLES(ICALL(ASSEMB_1, "UpdateNativeCustomAttributes", ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes)) ICALL(ASSEMB_2, "basic_init", ves_icall_AssemblyBuilder_basic_init) #ifndef DISABLE_REFLECTION_EMIT diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 3b4db614bba..2e8408bcac0 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -1926,8 +1926,8 @@ ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilderHandle mb void ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb); -MonoReflectionModule* -ves_icall_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName); +void +ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes (MonoReflectionAssemblyBuilderHandle assemblyb); MonoArray* ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues); diff --git a/mono/metadata/sre.c b/mono/metadata/sre.c index c2c3ac2d171..6a71565f4ca 100644 --- a/mono/metadata/sre.c +++ b/mono/metadata/sre.c @@ -4377,6 +4377,18 @@ ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb) mono_reflection_dynimage_basic_init (assemblyb); } +void +ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes (MonoReflectionAssemblyBuilderHandle assemblyb) +{ + MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs); + + MonoReflectionAssemblyHandle assembly_handle = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb); + MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly); + g_assert (assembly); + + mono_save_custom_attrs (assembly->image, assembly, MONO_HANDLE_RAW (cattrs)); +} + void ves_icall_EnumBuilder_setup_enum_type (MonoReflectionTypeHandle enumtype, MonoReflectionTypeHandle t,