From fdc109eebd9b05002c921e689b908de7dcb82f65 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 14 Jul 2018 11:30:59 +0200 Subject: [PATCH] Fix NullReferenceException in TypeSystemAstBuilder when attribute argument decoding fails. --- .../CSharp/OutputVisitor/CSharpOutputVisitor.cs | 2 +- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 9 ++++++++- ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj | 1 - ICSharpCode.Decompiler/TypeSystem/IAttribute.cs | 5 +++++ .../TypeSystem/Implementation/CustomAttribute.cs | 9 +++++++++ .../TypeSystem/Implementation/DefaultAttribute.cs | 4 +++- 6 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 6ee369c5d..52445918c 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -1288,7 +1288,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(attribute); attribute.Type.AcceptVisitor(this); - if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(Roles.LPar).IsNull) { + if (attribute.Arguments.Count != 0 || attribute.HasArgumentList) { Space(policy.SpaceBeforeMethodCallParentheses); WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses); } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index ee6dbe737..51964a4cf 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -471,9 +471,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9); } var parameters = attribute.Constructor?.Parameters ?? EmptyList.Instance; - foreach (var (arg, p) in attribute.FixedArguments.ZipLongest(parameters)) { + for (int i = 0; i < attribute.FixedArguments.Length; i++) { + var arg = attribute.FixedArguments[i]; + var p = (i < parameters.Count) ? parameters[i] : null; attr.Arguments.Add(ConvertConstantValue(p?.Type ?? arg.Type, arg.Type, arg.Value)); } + if (attribute.HasDecodeErrors) { + attr.HasArgumentList = true; + attr.AddChild(new Comment("Could not decode attribute arguments.", CommentType.MultiLine), Roles.Comment); + attr.AddChild(new CSharpTokenNode(TextLocation.Empty, Roles.RPar), Roles.RPar); + } if (attribute.NamedArguments.Length > 0) { InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType); foreach (var namedArg in attribute.NamedArguments) { diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 20331d7df..4826a9bab 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -274,7 +274,6 @@ - diff --git a/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs b/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs index 62b4f067b..e05f97769 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs @@ -40,6 +40,11 @@ namespace ICSharpCode.Decompiler.TypeSystem /// IMethod Constructor { get; } + /// + /// Gets whether there were errors decoding the attribute. + /// + bool HasDecodeErrors { get; } + /// /// Gets the positional arguments. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs index 3a5616af7..3d58038b5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs @@ -38,6 +38,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // lazy-loaded: CustomAttributeValue value; bool valueDecoded; + bool hasDecodeErrors; internal CustomAttribute(MetadataModule module, IMethod attrCtor, CustomAttributeHandle handle) { @@ -65,6 +66,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } + public bool HasDecodeErrors { + get { + DecodeValue(); + return hasDecodeErrors; + } + } + void DecodeValue() { lock (this) { @@ -80,6 +88,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation ImmutableArray>.Empty, ImmutableArray>.Empty ); + hasDecodeErrors = true; valueDecoded = true; // in case of errors, never try again. } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs index e5bef0a92..ca3d4935b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs @@ -66,7 +66,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IType AttributeType { get { return attributeType; } } - + + bool IAttribute.HasDecodeErrors => false; + public IMethod Constructor { get { IMethod ctor = this.constructor;