Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Attribute Validation #389

Closed
ds5678 opened this issue Dec 16, 2022 · 2 comments · Fixed by #407
Closed

Custom Attribute Validation #389

ds5678 opened this issue Dec 16, 2022 · 2 comments · Fixed by #407
Labels
dotnet Issues related to AsmResolver.DotNet enhancement
Milestone

Comments

@ds5678
Copy link
Contributor

ds5678 commented Dec 16, 2022

AsmResolver Version

5.0.0

.NET Version

.NET 6

Operating System

Windows

Describe the Bug

Assemblies created with AsmResolver seem to have invalid custom attribute blobs. Several problems were noticed when loading generated assemblies into popular .NET decompilers.

How To Reproduce

The bug was initially noticed in an assembly created by Cpp2IL with the latest NuGet version of AsmResolver. Although I cannot be sure that the 5.0 beta versions were without issue, I only noticed this in the full release.

In ILSpy 8 Preview 3, the assembly attributes are decoded like this:

using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: CompilationRelaxations(/*Could not decode attribute arguments.*/)]
[assembly: RuntimeCompatibility]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: InternalsVisibleTo(/*Could not decode attribute arguments.*/)]
[assembly: InternalsVisibleTo(/*Could not decode attribute arguments.*/)]
[assembly: AssemblyVersion("0.0.0.0")]

Similarly, dnSpyEx decompiles the assembly attributes as:

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyVersion("0.0.0.0")]
[assembly: CompilationRelaxations]
[assembly: RuntimeCompatibility]
[assembly: Debuggable]
[assembly: InternalsVisibleTo]
[assembly: InternalsVisibleTo]

However, not all cases are handled so cleanly. Attempting to view `` in ILSpy throws an exception:

System.BadImageFormatException: Read out of bounds.
   at System.Reflection.Throw.OutOfBounds()
   at System.Reflection.Metadata.Ecma335.CustomAttributeDecoder`1.DecodeNamedArguments(BlobReader& valueReader)
   at System.Reflection.Metadata.Ecma335.CustomAttributeDecoder`1.DecodeValue(EntityHandle constructor, BlobHandle value)
   at ICSharpCode.Decompiler.TypeSystem.MetadataModule.GetInternalsVisibleTo() in /_/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs:line 176
   at ICSharpCode.Decompiler.TypeSystem.MetadataModule.InternalsVisibleTo(IModule module) in /_/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs:line 151
   at ICSharpCode.Decompiler.CSharp.Resolver.CSharpResolver.LookInCurrentUsingScope(String identifier, IReadOnlyList`1 typeArguments, Boolean isInUsingDeclaration, Boolean parameterizeResultType) in /_/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs:line 1728
   at ICSharpCode.Decompiler.CSharp.Resolver.CSharpResolver.LookupSimpleNameOrTypeName(String identifier, IReadOnlyList`1 typeArguments, NameLookupMode lookupMode) in /_/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs:line 1609
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.ConvertTypeHelper(IType genericType, IReadOnlyList`1 typeArguments) in /_/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs:line 506
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.ConvertTypeHelper(IType type) in /_/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs:line 424
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.ConvertType(IType type) in /_/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs:line 238
   at ICSharpCode.Decompiler.CSharp.Transforms.IntroduceUsingDeclarations.FullyQualifyAmbiguousTypeNamesVisitor.VisitSimpleType(SimpleType simpleType) in /_/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs:line 319
   at ICSharpCode.Decompiler.CSharp.Syntax.DepthFirstAstVisitor.VisitChildren(AstNode node) in /_/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs:line 43
   at ICSharpCode.Decompiler.CSharp.Syntax.DepthFirstAstVisitor.VisitChildren(AstNode node) in /_/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs:line 43
   at ICSharpCode.Decompiler.CSharp.Transforms.IntroduceUsingDeclarations.FullyQualifyAmbiguousTypeNamesVisitor.Visit[T](T entityDeclaration, Action`1 baseCall) in /_/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs:line 289
   at ICSharpCode.Decompiler.CSharp.Syntax.DepthFirstAstVisitor.VisitChildren(AstNode node) in /_/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs:line 43
   at ICSharpCode.Decompiler.CSharp.Transforms.IntroduceUsingDeclarations.FullyQualifyAmbiguousTypeNamesVisitor.VisitTypeDeclaration(TypeDeclaration typeDeclaration) in /_/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs:line 226
   at ICSharpCode.Decompiler.CSharp.Syntax.DepthFirstAstVisitor.VisitChildren(AstNode node) in /_/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs:line 43
   at ICSharpCode.Decompiler.CSharp.Transforms.IntroduceUsingDeclarations.Run(AstNode rootNode, TransformContext context) in /_/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs:line 73
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.RunTransforms(AstNode rootNode, DecompileRun decompileRun, ITypeResolveContext decompilationContext) in /_/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs:line 564
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.Decompile(IEnumerable`1 definitions) in /_/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs:line 1088
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.Decompile(EntityHandle[] definitions) in /_/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs:line 1004
   at ICSharpCode.ILSpy.CSharpLanguage.DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
   at ICSharpCode.ILSpy.TreeNodes.TypeTreeNode.Decompile(Language language, ITextOutput output, DecompilationOptions options)
   at ICSharpCode.ILSpy.TextView.DecompilerTextView.DecompileNodes(DecompilationContext context, ITextOutput textOutput)
   at ICSharpCode.ILSpy.TextView.DecompilerTextView.<>c__DisplayClass52_0.<DecompileAsync>b__0()

dnSpyEx handles any problems silently and prints the following code:

using System;
using UnityEngine;
using UnityEngine.TextCore.LowLevel;

namespace TMPro
{
	[Serializable]
	public class TMP_GlyphPairAdjustmentRecord
	{
		public TMP_GlyphAdjustmentRecord firstAdjustmentRecord
		{
			get
			{
				return default(TMP_GlyphAdjustmentRecord);
			}
			set
			{
			}
		}

		public TMP_GlyphAdjustmentRecord secondAdjustmentRecord
		{
			get
			{
				return default(TMP_GlyphAdjustmentRecord);
			}
			set
			{
			}
		}

		public FontFeatureLookupFlags featureLookupFlags
		{
			get
			{
				return (FontFeatureLookupFlags)0;
			}
			set
			{
			}
		}

		public TMP_GlyphPairAdjustmentRecord(TMP_GlyphAdjustmentRecord firstAdjustmentRecord, TMP_GlyphAdjustmentRecord secondAdjustmentRecord)
		{
		}

		internal TMP_GlyphPairAdjustmentRecord(GlyphPairAdjustmentRecord glyphPairAdjustmentRecord)
		{
		}

		[SerializeField]
		private TMP_GlyphAdjustmentRecord m_FirstAdjustmentRecord;

		[SerializeField]
		private TMP_GlyphAdjustmentRecord m_SecondAdjustmentRecord;

		[SerializeField]
		private FontFeatureLookupFlags m_FeatureLookupFlags;
	}
}

Expected Behavior

The assemblies should be valid enough for decompilers to properly load and analyze them.

Actual Behavior

The decompilers fail to load custom attribute blobs.

Additional Context

No response

@ds5678 ds5678 added the bug label Dec 16, 2022
@ds5678 ds5678 changed the title Invalid Custom Attribute Blobs Custom Attribute Validation Dec 16, 2022
@ds5678
Copy link
Contributor Author

ds5678 commented Dec 16, 2022

As discussed in discord, this was caused by invalid input to AsmResolver which propagated into its output. Cpp2IL couldn't decode custom attributes on my Unity version, so it has nothing to fill attribute constructor parameters with. Instead of providing a default value for each parameter, Cpp2IL gave it nothing and caused this issue to occur. It would be nice if AsmResolver was able to provide some validation for custom attributes.

@Washi1337 Washi1337 added enhancement dotnet Issues related to AsmResolver.DotNet and removed bug labels Dec 17, 2022
@Washi1337 Washi1337 added this to the 5.1.0 milestone Dec 17, 2022
@Washi1337 Washi1337 linked a pull request Jan 26, 2023 that will close this issue
@Washi1337
Copy link
Owner

Washi1337 commented Jan 26, 2023

Implemented in #407 , will be available in 5.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dotnet Issues related to AsmResolver.DotNet enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants