Skip to content

Commit 8ad33f1

Browse files
committed
Fix #3479: If YieldReturnDecompiler.ConvertBody fails, abort transforming the state machine instead of continuing with invalid code.
1 parent dd4bf7d commit 8ad33f1

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,7 @@ private BlockContainer ConvertBody(BlockContainer oldBody, StateRangeAnalysis ra
885885
else
886886
{
887887
newBlock.Instructions.Add(new InvalidExpression("Assigned non-constant to iterator.state field").WithILRange(oldInst));
888+
ReportError(newBlock.Instructions.Last());
888889
continue; // don't copy over this instruction, but continue with the basic block
889890
}
890891
}
@@ -993,6 +994,7 @@ void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int pos)
993994
else
994995
{
995996
newBlock.Instructions.Add(new InvalidBranch("Unable to find new state assignment for yield return"));
997+
ReportError(newBlock.Instructions.Last());
996998
return;
997999
}
9981000
// Mono may have 'br setSkipFinallyBodies' here, so follow the branch
@@ -1009,6 +1011,7 @@ void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int pos)
10091011
ExpectedResultType = StackType.Void,
10101012
Message = "Unexpected assignment to skipFinallyBodies"
10111013
});
1014+
ReportError(newBlock.Instructions.Last());
10121015
}
10131016
pos++;
10141017
}
@@ -1022,6 +1025,7 @@ void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int pos)
10221025
ExpectedResultType = StackType.Void,
10231026
Message = "Unexpected assignment to doFinallyBodies"
10241027
});
1028+
ReportError(newBlock.Instructions.Last());
10251029
}
10261030
pos++;
10271031
}
@@ -1038,6 +1042,7 @@ void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int pos)
10381042
else
10391043
{
10401044
newBlock.Instructions.Add(new InvalidBranch("Unable to find 'return true' for yield return"));
1045+
ReportError(newBlock.Instructions.Last());
10411046
return;
10421047
}
10431048
newBlock.Instructions.Add(MakeGoTo(newState));
@@ -1068,7 +1073,9 @@ ILInstruction MakeGoTo(int v)
10681073
}
10691074
else
10701075
{
1071-
return new InvalidBranch("Could not find block for state " + v);
1076+
var err = new InvalidBranch("Could not find block for state " + v);
1077+
ReportError(err);
1078+
return err;
10721079
}
10731080
}
10741081

@@ -1100,6 +1107,8 @@ void UpdateBranchTargets(ILInstruction inst)
11001107
}
11011108
else
11021109
{
1110+
// don't treat this as an error, it might just be unreachable code that will be removed soon
1111+
// (occurs with mcs yield return)
11031112
leave.ReplaceWith(new InvalidBranch("Unexpected return in MoveNext()").WithILRange(leave));
11041113
}
11051114
}
@@ -1117,6 +1126,21 @@ void UpdateBranchTargets(ILInstruction inst)
11171126
UpdateBranchTargets(child);
11181127
}
11191128
}
1129+
1130+
void ReportError(ILInstruction inst)
1131+
{
1132+
// ConvertBody is still called within the try-catch, so we can throw SymbolicAnalysisFailedException
1133+
// to suppress conversion of the state machine altogether.
1134+
// We still initially create an instruction before converting a to an exception,
1135+
// so that the body of this function can be commented out for testing purposes.
1136+
// (this allows seeing where exactly the error occurs in the converted body output)
1137+
string message = "ConvertBody error";
1138+
if (inst is InvalidBranch invalidBranch)
1139+
message = invalidBranch.Message;
1140+
else if (inst is InvalidExpression invalidExpr)
1141+
message = invalidExpr.Message;
1142+
throw new SymbolicAnalysisFailedException(message);
1143+
}
11201144
}
11211145
#endregion
11221146

0 commit comments

Comments
 (0)