Browse Source

Fix #2366: NRE in AwaitInCatchTransform.MatchAwaitCatchHandler() and pattern errors when dealing with a switch-based jump table in AwaitInCatchTransform

pull/2373/head
Siegfried Pammer 5 years ago
parent
commit
7211587b45
  1. 34
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs
  2. 23
      ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs

34
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs

@ -306,6 +306,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
await Task.Yield(); await Task.Yield();
} }
} }
public async Task Issue2366a()
{
while (true)
{
try
{
await Task.CompletedTask;
}
catch
{
}
}
}
public async Task Issue2366b()
{
try
{
await Task.CompletedTask;
}
catch (NullReferenceException)
{
await Task.CompletedTask;
}
catch (InvalidOperationException)
{
await Task.CompletedTask;
}
catch (ArgumentException)
{
await Task.CompletedTask;
}
}
#endif #endif
public static async Task<int> GetIntegerSumAsync(IEnumerable<int> items) public static async Task<int> GetIntegerSumAsync(IEnumerable<int> items)

23
ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs

@ -66,6 +66,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
var cfg = new ControlFlowGraph(container, context.CancellationToken); var cfg = new ControlFlowGraph(container, context.CancellationToken);
if (transformableCatchBlocks.Count > 0) if (transformableCatchBlocks.Count > 0)
changedContainers.Add(container); changedContainers.Add(container);
SwitchInstruction switchInstructionOpt = null;
foreach (var result in transformableCatchBlocks) foreach (var result in transformableCatchBlocks)
{ {
removedBlocks.Clear(); removedBlocks.Clear();
@ -74,8 +75,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
context.StepStartGroup($"Inline catch block with await (at {result.Handler.Variable.Name})", result.Handler); context.StepStartGroup($"Inline catch block with await (at {result.Handler.Variable.Name})", result.Handler);
// Remove the IfInstruction from the jump table and eliminate all branches to the block. // Remove the IfInstruction from the jump table and eliminate all branches to the block.
if (result.JumpTableEntry is IfInstruction jumpTableEntry) switch (result.JumpTableEntry)
{ {
case IfInstruction jumpTableEntry:
var jumpTableBlock = (Block)jumpTableEntry.Parent; var jumpTableBlock = (Block)jumpTableEntry.Parent;
context.Step("Remove jump-table entry", result.JumpTableEntry); context.Step("Remove jump-table entry", result.JumpTableEntry);
jumpTableBlock.Instructions.RemoveAt(result.JumpTableEntry.ChildIndex); jumpTableBlock.Instructions.RemoveAt(result.JumpTableEntry.ChildIndex);
@ -96,6 +98,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} }
} }
} }
break;
case SwitchSection jumpTableEntry:
Debug.Assert(switchInstructionOpt == null || jumpTableEntry.Parent == switchInstructionOpt);
switchInstructionOpt = (SwitchInstruction)jumpTableEntry.Parent;
break;
} }
// Add the real catch block entry-point to the block container // Add the real catch block entry-point to the block container
@ -170,6 +177,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
context.StepEndGroup(keepIfEmpty: true); context.StepEndGroup(keepIfEmpty: true);
} }
if (switchInstructionOpt != null && switchInstructionOpt.Parent is Block b && b.IncomingEdgeCount > 0)
{
var defaultSection = switchInstructionOpt.GetDefaultSection();
foreach (var branch in container.Descendants.OfType<Branch>())
{
if (branch.TargetBlock != b)
continue;
branch.ReplaceWith(defaultSection.Body.Clone());
}
}
} }
// clean up all modified containers // clean up all modified containers
@ -275,6 +294,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!catchBlock.Instructions.Last().MatchBranch(out var jumpTableStartBlock)) if (!catchBlock.Instructions.Last().MatchBranch(out var jumpTableStartBlock))
return false; return false;
var identifierVariableAssignment = catchBlock.Instructions.SecondToLastOrDefault(); var identifierVariableAssignment = catchBlock.Instructions.SecondToLastOrDefault();
if (identifierVariableAssignment == null)
return false;
if (!identifierVariableAssignment.MatchStLoc(out identifierVariable, out value) || !value.MatchLdcI4(out id)) if (!identifierVariableAssignment.MatchStLoc(out identifierVariable, out value) || !value.MatchLdcI4(out id))
return false; return false;
// analyze jump table: // analyze jump table:

Loading…
Cancel
Save