Browse Source

Fix #3479: If YieldReturnDecompiler.ConvertBody fails, abort transforming the state machine instead of continuing with invalid code.

null-coalescing-assignment
Daniel Grunwald 4 months ago
parent
commit
8ad33f1e13
  1. 26
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

26
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -885,6 +885,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -885,6 +885,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
else
{
newBlock.Instructions.Add(new InvalidExpression("Assigned non-constant to iterator.state field").WithILRange(oldInst));
ReportError(newBlock.Instructions.Last());
continue; // don't copy over this instruction, but continue with the basic block
}
}
@ -993,6 +994,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -993,6 +994,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
else
{
newBlock.Instructions.Add(new InvalidBranch("Unable to find new state assignment for yield return"));
ReportError(newBlock.Instructions.Last());
return;
}
// Mono may have 'br setSkipFinallyBodies' here, so follow the branch
@ -1009,6 +1011,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1009,6 +1011,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
ExpectedResultType = StackType.Void,
Message = "Unexpected assignment to skipFinallyBodies"
});
ReportError(newBlock.Instructions.Last());
}
pos++;
}
@ -1022,6 +1025,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1022,6 +1025,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
ExpectedResultType = StackType.Void,
Message = "Unexpected assignment to doFinallyBodies"
});
ReportError(newBlock.Instructions.Last());
}
pos++;
}
@ -1038,6 +1042,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1038,6 +1042,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
else
{
newBlock.Instructions.Add(new InvalidBranch("Unable to find 'return true' for yield return"));
ReportError(newBlock.Instructions.Last());
return;
}
newBlock.Instructions.Add(MakeGoTo(newState));
@ -1068,7 +1073,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1068,7 +1073,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
else
{
return new InvalidBranch("Could not find block for state " + v);
var err = new InvalidBranch("Could not find block for state " + v);
ReportError(err);
return err;
}
}
@ -1100,6 +1107,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1100,6 +1107,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
else
{
// don't treat this as an error, it might just be unreachable code that will be removed soon
// (occurs with mcs yield return)
leave.ReplaceWith(new InvalidBranch("Unexpected return in MoveNext()").WithILRange(leave));
}
}
@ -1117,6 +1126,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1117,6 +1126,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
UpdateBranchTargets(child);
}
}
void ReportError(ILInstruction inst)
{
// ConvertBody is still called within the try-catch, so we can throw SymbolicAnalysisFailedException
// to suppress conversion of the state machine altogether.
// We still initially create an instruction before converting a to an exception,
// so that the body of this function can be commented out for testing purposes.
// (this allows seeing where exactly the error occurs in the converted body output)
string message = "ConvertBody error";
if (inst is InvalidBranch invalidBranch)
message = invalidBranch.Message;
else if (inst is InvalidExpression invalidExpr)
message = invalidExpr.Message;
throw new SymbolicAnalysisFailedException(message);
}
}
#endregion

Loading…
Cancel
Save