Browse Source

Fix NullReferenceException in TypeSystemAstBuilder when attribute argument decoding fails.

pull/1030/head
Daniel Grunwald 7 years ago
parent
commit
fdc109eebd
  1. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  2. 9
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 5
      ICSharpCode.Decompiler/TypeSystem/IAttribute.cs
  5. 9
      ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs
  6. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1288,7 +1288,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{ {
StartNode(attribute); StartNode(attribute);
attribute.Type.AcceptVisitor(this); attribute.Type.AcceptVisitor(this);
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(Roles.LPar).IsNull) { if (attribute.Arguments.Count != 0 || attribute.HasArgumentList) {
Space(policy.SpaceBeforeMethodCallParentheses); Space(policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses); WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
} }

9
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); mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9);
} }
var parameters = attribute.Constructor?.Parameters ?? EmptyList<IParameter>.Instance; var parameters = attribute.Constructor?.Parameters ?? EmptyList<IParameter>.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)); 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) { if (attribute.NamedArguments.Length > 0) {
InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType); InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType);
foreach (var namedArg in attribute.NamedArguments) { foreach (var namedArg in attribute.NamedArguments) {

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -274,7 +274,6 @@
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" /> <Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
<Compile Include="Documentation\IdStringMemberReference.cs" /> <Compile Include="Documentation\IdStringMemberReference.cs" />
<Compile Include="Documentation\IdStringProvider.cs" /> <Compile Include="Documentation\IdStringProvider.cs" />
<Compile Include="Documentation\XmlDocKeyProvider.cs" />
<Compile Include="Documentation\XmlDocLoader.cs" /> <Compile Include="Documentation\XmlDocLoader.cs" />
<Compile Include="Documentation\XmlDocumentationProvider.cs" /> <Compile Include="Documentation\XmlDocumentationProvider.cs" />
<Compile Include="IL\ControlFlow\AsyncAwaitDecompiler.cs" /> <Compile Include="IL\ControlFlow\AsyncAwaitDecompiler.cs" />

5
ICSharpCode.Decompiler/TypeSystem/IAttribute.cs

@ -40,6 +40,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
IMethod Constructor { get; } IMethod Constructor { get; }
/// <summary>
/// Gets whether there were errors decoding the attribute.
/// </summary>
bool HasDecodeErrors { get; }
/// <summary> /// <summary>
/// Gets the positional arguments. /// Gets the positional arguments.
/// </summary> /// </summary>

9
ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs

@ -38,6 +38,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded: // lazy-loaded:
CustomAttributeValue<IType> value; CustomAttributeValue<IType> value;
bool valueDecoded; bool valueDecoded;
bool hasDecodeErrors;
internal CustomAttribute(MetadataModule module, IMethod attrCtor, CustomAttributeHandle handle) 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() void DecodeValue()
{ {
lock (this) { lock (this) {
@ -80,6 +88,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
ImmutableArray<CustomAttributeTypedArgument<IType>>.Empty, ImmutableArray<CustomAttributeTypedArgument<IType>>.Empty,
ImmutableArray<CustomAttributeNamedArgument<IType>>.Empty ImmutableArray<CustomAttributeNamedArgument<IType>>.Empty
); );
hasDecodeErrors = true;
valueDecoded = true; // in case of errors, never try again. valueDecoded = true; // in case of errors, never try again.
} }
} }

2
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs

@ -67,6 +67,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return attributeType; } get { return attributeType; }
} }
bool IAttribute.HasDecodeErrors => false;
public IMethod Constructor { public IMethod Constructor {
get { get {
IMethod ctor = this.constructor; IMethod ctor = this.constructor;

Loading…
Cancel
Save