From 7f904f6c892e91138b531791452fd8c189f1924c Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sun, 1 Nov 2020 18:03:56 +0300 Subject: [PATCH] Emit IgnoresAccessChecksToAttribute for runtime-generated XAML --- build.sh | 2 +- .../AvaloniaXamlIlRuntimeCompiler.cs | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index a40e00f815..bd162fab9b 100755 --- a/build.sh +++ b/build.sh @@ -47,7 +47,7 @@ if [ -f "$DOTNET_GLOBAL_FILE" ]; then fi # If dotnet is installed locally, and expected version is not set or installation matches the expected version -if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then +if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") || "$SKIP_DOTNET_DOWNLOAD" == "1" ]]; then export DOTNET_EXE="$(command -v dotnet)" else DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs index d9b4cd70da..c69a651af2 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs @@ -26,6 +26,7 @@ namespace Avalonia.Markup.Xaml.XamlIl { #if !RUNTIME_XAML_CECIL private static SreTypeSystem _sreTypeSystem; + private static Type _ignoresAccessChecksFromAttribute; private static ModuleBuilder _sreBuilder; private static IXamlType _sreContextType; private static XamlLanguageTypeMappings _sreMappings; @@ -94,8 +95,58 @@ namespace Avalonia.Markup.Xaml.XamlIl _sreTypeSystem.CreateTypeBuilder( _sreBuilder.DefineType("XamlIlContext")), _sreTypeSystem, _sreMappings, _sreEmitMappings); + if (_ignoresAccessChecksFromAttribute == null) + _ignoresAccessChecksFromAttribute = EmitIgnoresAccessCheckAttributeDefinition(_sreBuilder); } + static Type EmitIgnoresAccessCheckAttributeDefinition(ModuleBuilder builder) + { + var tb = builder.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute", + TypeAttributes.Class | TypeAttributes.Public, typeof(Attribute)); + var field = tb.DefineField("_name", typeof(string), FieldAttributes.Private); + var propGet = tb.DefineMethod("get_AssemblyName", MethodAttributes.Public, typeof(string), + Array.Empty()); + var propGetIl = propGet.GetILGenerator(); + propGetIl.Emit(OpCodes.Ldarg_0); + propGetIl.Emit(OpCodes.Ldfld, field); + propGetIl.Emit(OpCodes.Ret); + var prop = tb.DefineProperty("AssemblyName", PropertyAttributes.None, typeof(string), Array.Empty()); + prop.SetGetMethod(propGet); + + + var ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, + new[] { typeof(string) }); + var ctorIl = ctor.GetILGenerator(); + ctorIl.Emit(OpCodes.Ldarg_0); + ctorIl.Emit(OpCodes.Ldarg_1); + ctorIl.Emit(OpCodes.Stfld, field); + ctorIl.Emit(OpCodes.Ldarg_0); + ctorIl.Emit(OpCodes.Call, typeof(Attribute) + .GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + .First(x => x.GetParameters().Length == 0)); + + ctorIl.Emit(OpCodes.Ret); + + tb.SetCustomAttribute(new CustomAttributeBuilder( + typeof(AttributeUsageAttribute).GetConstructor(new[] { typeof(AttributeTargets) }), + new object[] { AttributeTargets.Assembly }, + new[] { typeof(AttributeUsageAttribute).GetProperty("AllowMultiple") }, + new object[] { true })); + + return tb.CreateTypeInfo(); + } + + static void EmitIgnoresAccessCheckToAttribute(AssemblyName assemblyName) + { + var name = assemblyName.Name; + var key = assemblyName.GetPublicKey(); + if (key != null) + name += ", PublicKey=" + BitConverter.ToString(key).Replace("-", "").ToUpperInvariant(); + _sreAsm.SetCustomAttribute(new CustomAttributeBuilder( + _ignoresAccessChecksFromAttribute.GetConstructors()[0], + new object[] { name })); + } + static object LoadSre(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode) { @@ -118,6 +169,8 @@ namespace Avalonia.Markup.Xaml.XamlIl { InitializeSre(); + if (localAssembly?.FullName != null) + EmitIgnoresAccessCheckToAttribute(localAssembly.GetName()); var asm = localAssembly == null ? null : _sreTypeSystem.GetAssembly(localAssembly); var tb = _sreBuilder.DefineType("Builder_" + Guid.NewGuid().ToString("N") + "_" + uri); var clrPropertyBuilder = tb.DefineNestedType("ClrProperties_" + Guid.NewGuid().ToString("N"));