Browse Source

Fix crash when control flow reaches end of method.

pull/2993/head
Daniel Grunwald 2 years ago
parent
commit
94d2ce0fcf
  1. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  2. 14
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.cs
  3. 45
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.il
  4. 15
      ICSharpCode.Decompiler/IL/ILReader.cs

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -263,6 +263,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -263,6 +263,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
[Test]
public async Task EmptyBodies()
{
await Run();
}
async Task Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
AssemblerOptions assemblerOptions = AssemblerOptions.Library)
{

14
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
internal class EmptyBodies
{
public static void RetVoid()
{
}
public static int RetInt()
{
return (int)/*Error near IL_0001: Stack underflow*/;
}
public static void Nop()
{
/*Error: End of method reached without returning.*/;
}
}

45
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.il

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
#define CORE_ASSEMBLY "System.Runtime"
.assembly extern CORE_ASSEMBLY
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:0:0:0
}
.class private auto ansi beforefieldinit EmptyBodies
extends [CORE_ASSEMBLY]System.Object
{
// I cannot test a truly empty body because the assembler will automatically add a ret instruction.
.method public hidebysig static void RetVoid () cil managed
{
.maxstack 8
ret
}
.method public hidebysig static int32 RetInt () cil managed
{
.maxstack 8
ret
}
.method public hidebysig static void Nop () cil managed
{
.maxstack 8
nop
}
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x206e
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Example::.ctor
} // end of class EmptyBodies

15
ICSharpCode.Decompiler/IL/ILReader.cs

@ -535,16 +535,25 @@ namespace ICSharpCode.Decompiler.IL @@ -535,16 +535,25 @@ namespace ICSharpCode.Decompiler.IL
if (!block.Block.HasFlag(InstructionFlags.EndPointUnreachable))
{
// create fall through branch
MarkBranchTarget(reader.Offset, isFallThrough: true);
ILInstruction branch;
if (reader.RemainingBytes > 0)
{
MarkBranchTarget(reader.Offset, isFallThrough: true);
branch = new Branch(reader.Offset);
}
else
{
branch = new InvalidBranch("End of method reached without returning.");
}
if (block.Block.Instructions.LastOrDefault() is SwitchInstruction switchInst && switchInst.Sections.Last().Body.MatchNop())
{
// Instead of putting the default branch after the switch instruction
switchInst.Sections.Last().Body = new Branch(reader.Offset);
switchInst.Sections.Last().Body = branch;
Debug.Assert(switchInst.HasFlag(InstructionFlags.EndPointUnreachable));
}
else
{
block.Block.Instructions.Add(new Branch(reader.Offset));
block.Block.Instructions.Add(branch);
}
}
}

Loading…
Cancel
Save