Browse Source

Fix #1283: handle invalid metadata when decoding constants

pull/1360/head
Daniel Grunwald 7 years ago
parent
commit
72d755037b
  1. 40
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  2. 17
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  4. 2
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs
  5. 2
      ICSharpCode.Decompiler/CSharp/Resolver/MemberLookup.cs
  6. 15
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs
  7. 34
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  8. 8
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  9. 2
      ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs
  10. 4
      ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs
  11. 4
      ICSharpCode.Decompiler/TypeSystem/IVariable.cs
  12. 10
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
  13. 5
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultVariable.cs
  14. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
  15. 19
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  16. 13
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  17. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs
  18. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs

40
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs

@ -496,24 +496,24 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsTrue(f.IsConst); Assert.IsTrue(f.IsConst);
Assert.AreEqual(Accessibility.Public, f.Accessibility); Assert.AreEqual(Accessibility.Public, f.Accessibility);
Assert.AreSame(e, f.Type); Assert.AreSame(e, f.Type);
Assert.AreEqual(typeof(short), f.ConstantValue.GetType()); Assert.AreEqual(typeof(short), f.GetConstantValue().GetType());
} }
Assert.AreEqual("First", fields[0].Name); Assert.AreEqual("First", fields[0].Name);
Assert.AreEqual(0, fields[0].ConstantValue); Assert.AreEqual(0, fields[0].GetConstantValue());
Assert.AreEqual("Second", fields[1].Name); Assert.AreEqual("Second", fields[1].Name);
Assert.AreSame(e, fields[1].Type); Assert.AreSame(e, fields[1].Type);
Assert.AreEqual(1, fields[1].ConstantValue); Assert.AreEqual(1, fields[1].GetConstantValue());
Assert.AreEqual("Flag1", fields[2].Name); Assert.AreEqual("Flag1", fields[2].Name);
Assert.AreEqual(0x10, fields[2].ConstantValue); Assert.AreEqual(0x10, fields[2].GetConstantValue());
Assert.AreEqual("Flag2", fields[3].Name); Assert.AreEqual("Flag2", fields[3].Name);
Assert.AreEqual(0x20, fields[3].ConstantValue); Assert.AreEqual(0x20, fields[3].GetConstantValue());
Assert.AreEqual("CombinedFlags", fields[4].Name); Assert.AreEqual("CombinedFlags", fields[4].Name);
Assert.AreEqual(0x30, fields[4].ConstantValue); Assert.AreEqual(0x30, fields[4].GetConstantValue());
} }
[Test] [Test]
@ -773,7 +773,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual(4, p.ConstantValue); Assert.AreEqual(4, p.GetConstantValue());
} }
[Test] [Test]
@ -799,7 +799,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.ConstantValue); Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.GetConstantValue());
} }
[Test] [Test]
@ -812,7 +812,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsNull(p.ConstantValue); Assert.IsNull(p.GetConstantValue());
} }
[Test] [Test]
@ -824,8 +824,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.ConstantValue); Assert.AreEqual(1L, p.GetConstantValue());
Assert.AreEqual(typeof(long), p.ConstantValue.GetType()); Assert.AreEqual(typeof(long), p.GetConstantValue().GetType());
} }
[Test] [Test]
@ -837,8 +837,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.ConstantValue); Assert.AreEqual(1L, p.GetConstantValue());
Assert.AreEqual(typeof(long), p.ConstantValue.GetType()); Assert.AreEqual(typeof(long), p.GetConstantValue().GetType());
} }
[Test] [Test]
@ -850,8 +850,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1M, p.ConstantValue); Assert.AreEqual(1M, p.GetConstantValue());
Assert.AreEqual(typeof(decimal), p.ConstantValue.GetType()); Assert.AreEqual(typeof(decimal), p.GetConstantValue().GetType());
} }
[Test] [Test]
@ -1509,7 +1509,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
ITypeDefinition type = GetTypeDefinition(typeof(ClassWithMethodThatHasNullableDefaultParameter)); ITypeDefinition type = GetTypeDefinition(typeof(ClassWithMethodThatHasNullableDefaultParameter));
var method = type.GetMethods().Single(m => m.Name == "Foo"); var method = type.GetMethods().Single(m => m.Name == "Foo");
Assert.AreEqual(42, method.Parameters.Single().ConstantValue); Assert.AreEqual(42, method.Parameters.Single().GetConstantValue());
} }
[Test] [Test]
@ -1529,7 +1529,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
var f = type.GetFields().Single(x => x.Name == name); var f = type.GetFields().Single(x => x.Name == name);
Assert.IsTrue(f.IsConst); Assert.IsTrue(f.IsConst);
Assert.AreEqual(expected, f.ConstantValue); Assert.AreEqual(expected, f.GetConstantValue());
Assert.AreEqual(0, f.GetAttributes().Count()); Assert.AreEqual(0, f.GetAttributes().Count());
} }
@ -1577,7 +1577,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest)); ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest));
IField field = type.Fields.Single(f => f.Name == "EnumFromThisAssembly"); IField field = type.Fields.Single(f => f.Name == "EnumFromThisAssembly");
Assert.IsTrue(field.IsConst); Assert.IsTrue(field.IsConst);
Assert.AreEqual((short)MyEnum.Second, field.ConstantValue); Assert.AreEqual((short)MyEnum.Second, field.GetConstantValue());
} }
[Test] [Test]
@ -1586,7 +1586,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest)); ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest));
IField field = type.Fields.Single(f => f.Name == "EnumFromAnotherAssembly"); IField field = type.Fields.Single(f => f.Name == "EnumFromAnotherAssembly");
Assert.IsTrue(field.IsConst); Assert.IsTrue(field.IsConst);
Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, field.ConstantValue); Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, field.GetConstantValue());
} }
[Test] [Test]
@ -1595,7 +1595,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest)); ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest));
IField field = type.Fields.Single(f => f.Name == "DefaultOfEnum"); IField field = type.Fields.Single(f => f.Name == "DefaultOfEnum");
Assert.IsTrue(field.IsConst); Assert.IsTrue(field.IsConst);
Assert.AreEqual((short)default(MyEnum), field.ConstantValue); Assert.AreEqual((short)default(MyEnum), field.GetConstantValue());
} }
[Test] [Test]

17
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -998,7 +998,7 @@ namespace ICSharpCode.Decompiler.CSharp
case EnumValueDisplayMode.None: case EnumValueDisplayMode.None:
foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>()) { foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>()) {
enumMember.Initializer = null; enumMember.Initializer = null;
if (enumMember.GetSymbol() is IField f && f.ConstantValue == null) { if (enumMember.GetSymbol() is IField f && f.GetConstantValue() == null) {
typeDecl.InsertChildBefore(enumMember, new Comment(" error: enumerator has no value"), Roles.Comment); typeDecl.InsertChildBefore(enumMember, new Comment(" error: enumerator has no value"), Roles.Comment);
} }
} }
@ -1030,8 +1030,12 @@ namespace ICSharpCode.Decompiler.CSharp
bool first = true; bool first = true;
long firstValue = 0, previousValue = 0; long firstValue = 0, previousValue = 0;
foreach (var field in typeDef.Fields) { foreach (var field in typeDef.Fields) {
if (MemberIsHidden(module, field.MetadataToken, settings) || field.ConstantValue == null) continue; if (MemberIsHidden(module, field.MetadataToken, settings))
long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); continue;
object constantValue = field.GetConstantValue();
if (constantValue == null)
continue;
long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false);
if (first) { if (first) {
firstValue = currentValue; firstValue = currentValue;
first = false; first = false;
@ -1260,9 +1264,10 @@ namespace ICSharpCode.Decompiler.CSharp
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum) { if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum) {
var enumDec = new EnumMemberDeclaration { Name = field.Name }; var enumDec = new EnumMemberDeclaration { Name = field.Name };
if (field.ConstantValue != null) { object constantValue = field.GetConstantValue();
long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); if (constantValue != null) {
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue); long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false);
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, constantValue);
if (enumDec.Initializer is PrimitiveExpression primitive if (enumDec.Initializer is PrimitiveExpression primitive
&& initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags) && initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags)
|| (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) { || (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) {

2
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -714,7 +714,7 @@ namespace ICSharpCode.Decompiler.CSharp
|| a.AttributeType.IsKnownType(KnownAttribute.CallerFilePath) || a.AttributeType.IsKnownType(KnownAttribute.CallerFilePath)
|| a.AttributeType.IsKnownType(KnownAttribute.CallerLineNumber))) || a.AttributeType.IsKnownType(KnownAttribute.CallerLineNumber)))
return false; return false;
return object.Equals(parameter.ConstantValue, arg.ResolveResult.ConstantValue); return object.Equals(parameter.GetConstantValue(), arg.ResolveResult.ConstantValue);
} }
[Flags] [Flags]

2
ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs

@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
for (int i = 0; i < results.Length; i++) { for (int i = 0; i < results.Length; i++) {
if (results[i] == null) { if (results[i] == null) {
if (Member.Parameters[i].IsOptional) { if (Member.Parameters[i].IsOptional) {
results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].ConstantValue); results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].GetConstantValue());
} else { } else {
results[i] = ErrorResolveResult.UnknownError; results[i] = ErrorResolveResult.UnknownError;
} }

2
ICSharpCode.Decompiler/CSharp/Resolver/MemberLookup.cs

@ -684,7 +684,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return new MemberResolveResult( return new MemberResolveResult(
targetResolveResult, field, targetResolveResult, field,
field.DeclaringTypeDefinition.EnumUnderlyingType, field.DeclaringTypeDefinition.EnumUnderlyingType,
field.IsConst, field.ConstantValue); field.IsConst, field.GetConstantValue());
} }
} }
return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod); return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod);

15
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs

@ -52,22 +52,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
} }
public ErrorExpression (TextLocation location)
{
this.Location = location;
}
public ErrorExpression (string error) public ErrorExpression (string error)
{ {
this.Error = error; AddChild(new Comment(error, CommentType.MultiLine), Roles.Comment);
}
public ErrorExpression (string error, TextLocation location)
{
this.Location = location;
this.Error = error;
} }
public override void AcceptVisitor (IAstVisitor visitor) public override void AcceptVisitor (IAstVisitor visitor)
{ {
visitor.VisitErrorNode(this); visitor.VisitErrorNode(this);

34
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -852,8 +852,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
ITypeDefinition enumDefinition = type.GetDefinition(); ITypeDefinition enumDefinition = type.GetDefinition();
TypeCode enumBaseTypeCode = ReflectionHelper.GetTypeCode(enumDefinition.EnumUnderlyingType); TypeCode enumBaseTypeCode = ReflectionHelper.GetTypeCode(enumDefinition.EnumUnderlyingType);
foreach (IField field in enumDefinition.Fields) { foreach (IField field in enumDefinition.Fields.Where(fld => fld.IsConst)) {
if (field.IsConst && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false), val)) { object constantValue = field.GetConstantValue();
if (constantValue == null)
continue;
if (object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false), val)) {
MemberReferenceExpression mre = new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(type)), field.Name); MemberReferenceExpression mre = new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(type)), field.Name);
if (AddResolveResultAnnotations) if (AddResolveResultAnnotations)
mre.AddAnnotation(new MemberResolveResult(mre.Target.GetResolveResult(), field)); mre.AddAnnotation(new MemberResolveResult(mre.Target.GetResolveResult(), field));
@ -881,7 +884,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
Expression negatedExpr = null; Expression negatedExpr = null;
foreach (IField field in enumDefinition.Fields.Where(fld => fld.IsConst)) { foreach (IField field in enumDefinition.Fields.Where(fld => fld.IsConst)) {
long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); object constantValue = field.GetConstantValue();
long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false);
if (fieldValue == 0) if (fieldValue == 0)
continue; // skip None enum value continue; // skip None enum value
@ -946,7 +950,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.Name = parameter.Name; decl.Name = parameter.Name;
} }
if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues) { if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues) {
decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.ConstantValue); try {
decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.GetConstantValue(throwOnInvalidMetadata: true));
} catch (BadImageFormatException ex) {
decl.DefaultExpression = new ErrorExpression(ex.Message);
}
} }
return decl; return decl;
} }
@ -1158,8 +1166,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
decl.ReturnType = ConvertType(field.ReturnType); decl.ReturnType = ConvertType(field.ReturnType);
Expression initializer = null; Expression initializer = null;
if (field.IsConst && this.ShowConstantValues) if (field.IsConst && this.ShowConstantValues) {
initializer = ConvertConstantValue(field.Type, field.ConstantValue); try {
initializer = ConvertConstantValue(field.Type, field.GetConstantValue(throwOnInvalidMetadata: true));
} catch (BadImageFormatException ex) {
initializer = new ErrorExpression(ex.Message);
}
}
decl.Variables.Add(new VariableInitializer(field.Name, initializer)); decl.Variables.Add(new VariableInitializer(field.Name, initializer));
return decl; return decl;
} }
@ -1463,8 +1476,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None; decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None;
decl.Type = ConvertType(v.Type); decl.Type = ConvertType(v.Type);
Expression initializer = null; Expression initializer = null;
if (v.IsConst) if (v.IsConst) {
initializer = ConvertConstantValue(v.Type, v.ConstantValue); try {
initializer = ConvertConstantValue(v.Type, v.GetConstantValue(throwOnInvalidMetadata: true));
} catch (BadImageFormatException ex) {
initializer = new ErrorExpression(ex.Message);
}
}
decl.Variables.Add(new VariableInitializer(v.Name, initializer)); decl.Variables.Add(new VariableInitializer(v.Name, initializer));
return decl; return decl;
} }

8
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -1025,7 +1025,13 @@ namespace ICSharpCode.Decompiler.Disassembler
break; break;
default: default:
var blob = metadata.GetBlobReader(constant.Value); var blob = metadata.GetBlobReader(constant.Value);
var value = blob.ReadConstant(constant.TypeCode); object value;
try {
value = blob.ReadConstant(constant.TypeCode);
} catch (ArgumentOutOfRangeException) {
output.Write($"/* Constant with invalid typecode: {constant.TypeCode} */");
return;
}
if (value is string) { if (value is string) {
DisassemblerHelpers.WriteOperand(output, value); DisassemblerHelpers.WriteOperand(output, value);
} else { } else {

2
ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Semantics
} }
public override object ConstantValue { public override object ConstantValue {
get { return IsParameter ? null : variable.ConstantValue; } get { return IsParameter ? null : variable.GetConstantValue(); }
} }
public override string ToString() public override string ToString()

4
ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs

@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.Semantics
if (field != null) { if (field != null) {
isConstant = field.IsConst; isConstant = field.IsConst;
if (isConstant) if (isConstant)
constantValue = field.ConstantValue; constantValue = field.GetConstantValue();
} }
} }
@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.Semantics
if (field != null) { if (field != null) {
isConstant = field.IsConst; isConstant = field.IsConst;
if (isConstant) if (isConstant)
constantValue = field.ConstantValue; constantValue = field.GetConstantValue();
} }
} }

4
ICSharpCode.Decompiler/TypeSystem/IVariable.cs

@ -37,11 +37,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Gets whether this variable is a constant (C#-like const). /// Gets whether this variable is a constant (C#-like const).
/// </summary> /// </summary>
bool IsConst { get; } bool IsConst { get; }
/// <summary> /// <summary>
/// If this field is a constant, retrieves the value. /// If this field is a constant, retrieves the value.
/// For parameters, this is the default value. /// For parameters, this is the default value.
/// </summary> /// </summary>
object ConstantValue { get; } object GetConstantValue(bool throwOnInvalidMetadata = false);
} }
} }

10
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs

@ -111,8 +111,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return IsOptional; } get { return IsOptional; }
} }
public object ConstantValue { public object GetConstantValue(bool throwOnInvalidMetadata)
get { return defaultValue; } {
return defaultValue;
} }
public override string ToString() public override string ToString()
@ -134,8 +135,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Append(parameter.Type.ReflectionName); b.Append(parameter.Type.ReflectionName);
if (parameter.IsOptional && parameter.HasConstantValueInSignature) { if (parameter.IsOptional && parameter.HasConstantValueInSignature) {
b.Append(" = "); b.Append(" = ");
if (parameter.ConstantValue != null) object val = parameter.GetConstantValue(throwOnInvalidMetadata: false);
b.Append(parameter.ConstantValue.ToString()); if (val != null)
b.Append(val.ToString());
else else
b.Append("null"); b.Append("null");
} }

5
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultVariable.cs

@ -60,8 +60,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return isConst; } get { return isConst; }
} }
public object ConstantValue { public object GetConstantValue(bool throwOnInvalidMetadata)
get { return constantValue; } {
return constantValue;
} }
public SymbolKind SymbolKind { public SymbolKind SymbolKind {

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

@ -108,7 +108,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IField.IsVolatile => false; bool IField.IsVolatile => false;
bool IVariable.IsConst => false; bool IVariable.IsConst => false;
object IVariable.ConstantValue => null; object IVariable.GetConstantValue(bool throwOnInvalidMetadata) => null;
IType IVariable.Type => ReturnType; IType IVariable.Type => ReturnType;
public override SymbolKind SymbolKind => SymbolKind.Field; public override SymbolKind SymbolKind => SymbolKind.Field;

19
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs

@ -201,11 +201,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
public object ConstantValue { public object GetConstantValue(bool throwOnInvalidMetadata)
get { {
object val = LazyInit.VolatileRead(ref this.constantValue); object val = LazyInit.VolatileRead(ref this.constantValue);
if (val != null) if (val != null)
return val; return val;
try {
var metadata = module.metadata; var metadata = module.metadata;
var fieldDef = metadata.GetFieldDefinition(handle); var fieldDef = metadata.GetFieldDefinition(handle);
if (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module)) { if (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module)) {
@ -216,9 +217,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return null; return null;
var constant = metadata.GetConstant(constantHandle); var constant = metadata.GetConstant(constantHandle);
var blobReader = metadata.GetBlobReader(constant.Value); var blobReader = metadata.GetBlobReader(constant.Value);
val = blobReader.ReadConstant(constant.TypeCode); try {
val = blobReader.ReadConstant(constant.TypeCode);
} catch (ArgumentOutOfRangeException) {
throw new BadImageFormatException($"Constant with invalid typecode: {constant.TypeCode}");
}
} }
return LazyInit.GetOrSet(ref this.constantValue, val); return LazyInit.GetOrSet(ref this.constantValue, val);
} catch (BadImageFormatException) when (!throwOnInvalidMetadata) {
return null;
} }
} }

13
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

@ -130,8 +130,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IVariable.IsConst => false; bool IVariable.IsConst => false;
public object ConstantValue { public object GetConstantValue(bool throwOnInvalidMetadata)
get { {
try {
var metadata = module.metadata; var metadata = module.metadata;
var parameterDef = metadata.GetParameter(handle); var parameterDef = metadata.GetParameter(handle);
if (IsDecimalConstant) if (IsDecimalConstant)
@ -143,7 +144,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var constant = metadata.GetConstant(constantHandle); var constant = metadata.GetConstant(constantHandle);
var blobReader = metadata.GetBlobReader(constant.Value); var blobReader = metadata.GetBlobReader(constant.Value);
return blobReader.ReadConstant(constant.TypeCode); try {
return blobReader.ReadConstant(constant.TypeCode);
} catch (ArgumentOutOfRangeException) {
throw new BadImageFormatException($"Constant with invalid typecode: {constant.TypeCode}");
}
} catch (BadImageFormatException) when (!throwOnInvalidMetadata) {
return null;
} }
} }

4
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs

@ -60,8 +60,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return fieldDefinition.IsConst; } get { return fieldDefinition.IsConst; }
} }
public object ConstantValue { public object GetConstantValue(bool throwOnInvalidMetadata) {
get { return fieldDefinition.ConstantValue; } return fieldDefinition.GetConstantValue(throwOnInvalidMetadata);
} }
} }
} }

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

@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
string ISymbol.Name => baseParameter.Name; string ISymbol.Name => baseParameter.Name;
IType IVariable.Type => newType; IType IVariable.Type => newType;
bool IVariable.IsConst => baseParameter.IsConst; bool IVariable.IsConst => baseParameter.IsConst;
object IVariable.ConstantValue => baseParameter.ConstantValue; object IVariable.GetConstantValue(bool throwOnInvalidMetadata) => baseParameter.GetConstantValue(throwOnInvalidMetadata);
SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter; SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter;
public override string ToString() public override string ToString()

Loading…
Cancel
Save