From 4e8ebbf7f43efc50d5bd1e4ab97e047a8ebd8faf Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 16 Jul 2018 23:11:19 +0200 Subject: [PATCH] Fix #1189: Avoid crashing on invalid IL bytes. --- .../InsertMissingTokensDecorator.cs | 19 +++--- .../CSharp/RequiredNamespaceCollector.cs | 58 +++++++++++++++---- .../Syntax/Expressions/ErrorExpression.cs | 10 ++-- ICSharpCode.Decompiler/IL/ILReader.cs | 2 +- .../TypeSystem/MetadataModule.cs | 4 +- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs index 1a24e8339..220a9194e 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs @@ -68,13 +68,18 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public override void WriteToken(Role role, string token) { - EmptyStatement node = nodes.Peek().LastOrDefault() as EmptyStatement; - if (node == null) { - CSharpTokenNode t = new CSharpTokenNode(locationProvider.Location, (TokenRole)role); - t.Role = role; - currentList.Add(t); - } else { - node.Location = locationProvider.Location; + switch (nodes.Peek().LastOrDefault()) { + case EmptyStatement emptyStatement: + emptyStatement.Location = locationProvider.Location; + break; + case ErrorExpression errorExpression: + errorExpression.Location = locationProvider.Location; + break; + default: + CSharpTokenNode t = new CSharpTokenNode(locationProvider.Location, (TokenRole)role); + t.Role = role; + currentList.Add(t); + break; } base.WriteToken(role, token); } diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index bc856314b..d1338144c 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -188,12 +188,24 @@ namespace ICSharpCode.Decompiler.CSharp } foreach (var region in method.ExceptionRegions) { - if (region.CatchType.IsNil) continue; - CollectNamespacesForTypeReference(module.ResolveType(region.CatchType, genericContext), namespaces); + if (region.CatchType.IsNil) + continue; + IType ty; + try { + ty = module.ResolveType(region.CatchType, genericContext); + } catch (BadImageFormatException) { + continue; + } + CollectNamespacesForTypeReference(ty, namespaces); } while (instructions.RemainingBytes > 0) { - var opCode = instructions.DecodeOpCode(); + ILOpCode opCode; + try { + opCode = instructions.DecodeOpCode(); + } catch (BadImageFormatException) { + return; + } switch (opCode.GetOperandType()) { case Metadata.OperandType.Field: case Metadata.OperandType.Method: @@ -201,24 +213,46 @@ namespace ICSharpCode.Decompiler.CSharp case Metadata.OperandType.Tok: case Metadata.OperandType.Type: var handle = MetadataTokenHelpers.EntityHandleOrNil(instructions.ReadInt32()); - if (handle.IsNil) break; + if (handle.IsNil) + break; switch (handle.Kind) { case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: - CollectNamespacesForTypeReference(module.ResolveType(handle, genericContext), namespaces); + IType type; + try { + type = module.ResolveType(handle, genericContext); + } catch (BadImageFormatException) { + break; + } + CollectNamespacesForTypeReference(type, namespaces); break; case HandleKind.FieldDefinition: case HandleKind.MethodDefinition: case HandleKind.MethodSpecification: case HandleKind.MemberReference: - CollectNamespacesForMemberReference(module.ResolveEntity(handle, genericContext) as IMember, - module, namespaces); + IMember member; + try { + member = module.ResolveEntity(handle, genericContext) as IMember; + } catch (BadImageFormatException) { + break; + } + CollectNamespacesForMemberReference(member, module, namespaces); break; case HandleKind.StandaloneSignature: - var sig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)handle); + StandaloneSignature sig; + try { + sig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)handle); + } catch (BadImageFormatException) { + break; + } if (sig.GetKind() == StandaloneSignatureKind.Method) { - var methodSig = module.DecodeMethodSignature((StandaloneSignatureHandle)handle, genericContext); + MethodSignature methodSig; + try { + methodSig = module.DecodeMethodSignature((StandaloneSignatureHandle)handle, genericContext); + } catch (BadImageFormatException) { + break; + } CollectNamespacesForTypeReference(methodSig.ReturnType, namespaces); foreach (var paramType in methodSig.ParameterTypes) { CollectNamespacesForTypeReference(paramType, namespaces); @@ -228,7 +262,11 @@ namespace ICSharpCode.Decompiler.CSharp } break; default: - instructions.SkipOperand(opCode); + try { + instructions.SkipOperand(opCode); + } catch (BadImageFormatException) { + return; + } break; } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs index b7983b0bc..37beb3e80 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs @@ -29,17 +29,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public class ErrorExpression : Expression { - TextLocation location; + public TextLocation Location { get; set; } public override TextLocation StartLocation { get { - return location; + return Location; } } public override TextLocation EndLocation { get { - return location; + return Location; } } @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ErrorExpression (TextLocation location) { - this.location = location; + this.Location = location; } public ErrorExpression (string error) @@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ErrorExpression (string error, TextLocation location) { - this.location = location; + this.Location = location; this.Error = error; } diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index a59143ba9..6059cd93d 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -388,7 +388,7 @@ namespace ICSharpCode.Decompiler.IL } catch (BadImageFormatException ex) { decodedInstruction = new InvalidBranch(ex.Message); } - if (decodedInstruction.ResultType == StackType.Unknown) + if (decodedInstruction.ResultType == StackType.Unknown && decodedInstruction.OpCode != OpCode.InvalidBranch && UnpackPush(decodedInstruction).OpCode != OpCode.InvalidExpression) Warn("Unknown result type (might be due to invalid IL or missing references)"); decodedInstruction.CheckInvariant(ILPhase.InILReader); int end = reader.Offset; diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index 27c2420e0..6a7378c40 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -278,9 +278,7 @@ namespace ICSharpCode.Decompiler.TypeSystem case HandleKind.ExportedType: return ResolveForwardedType(metadata.GetExportedType((ExportedTypeHandle)typeRefDefSpec)); default: - Debug.Fail("Not a type handle"); - ty = SpecialType.UnknownType; - break; + throw new BadImageFormatException("Not a type handle"); } ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, typeAttributes, metadata, customOptions); return ty;