Skip to content

Commit 38489b9

Browse files
[clr-interp] Fix EH logic edge case (#122993)
When a try block exactly encloses another try/finally or try/catch block and the handler ends at the same point the try body ends we had an off by one issue in our reprentation of the ilOffset on the leave chain islands. This fixes the off by one issue for that kind of basic block. The C# compiler seems to always inject a nop to avoid this issue, but I do not know why and I can find no justification for that rule. Fixes badcodeinsidefinally tests
1 parent 768a134 commit 38489b9

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,13 +1097,21 @@ void InterpCompiler::EmitCode()
10971097
getEHinfo(m_methodInfo, i, &clause);
10981098
for (InterpBasicBlock *bb = m_pEntryBB; bb != NULL; bb = bb->pNextBB)
10991099
{
1100+
if (bb->isLeaveChainIsland && clause.HandlerOffset == (uint32_t)bb->ilOffset)
1101+
{
1102+
// Leave chain islands are not part of any EH clause, but their IL offset may be
1103+
continue;
1104+
}
1105+
11001106
if (clause.HandlerOffset <= (uint32_t)bb->ilOffset && (clause.HandlerOffset + clause.HandlerLength) > (uint32_t)bb->ilOffset)
11011107
{
1108+
INTERP_DUMP("BB %d with ilOffset %x overlaps EH clause %d (handler)\n", bb->index, bb->ilOffset, i);
11021109
bb->overlappingEHClauseCount++;
11031110
}
11041111

11051112
if (clause.Flags == CORINFO_EH_CLAUSE_FILTER && clause.FilterOffset <= (uint32_t)bb->ilOffset && clause.HandlerOffset > (uint32_t)bb->ilOffset)
11061113
{
1114+
INTERP_DUMP("BB %d with ilOffset %x overlaps EH clause %d (filter)\n", bb->index, bb->ilOffset, i);
11071115
bb->overlappingEHClauseCount++;
11081116
}
11091117
}
@@ -1569,6 +1577,7 @@ void InterpCompiler::GetNativeRangeForClause(uint32_t startILOffset, uint32_t en
15691577
assert(pStartBB != NULL);
15701578

15711579
InterpBasicBlock* pEndBB = pStartBB;
1580+
15721581
for (InterpBasicBlock* pBB = pStartBB->pNextBB; (pBB != NULL) && ((uint32_t)pBB->ilOffset < endILOffset); pBB = pBB->pNextBB)
15731582
{
15741583
if (pBB->overlappingEHClauseCount == pStartBB->overlappingEHClauseCount)
@@ -1682,6 +1691,18 @@ void InterpCompiler::BuildEHInfo()
16821691
m_compHnd->setEHcount(nativeEHCount);
16831692

16841693
unsigned int nativeEHIndex = 0;
1694+
1695+
#ifdef DEBUG
1696+
INTERP_DUMP(" BB overlapping EH clause counts:\n");
1697+
if (t_interpDump)
1698+
{
1699+
for (InterpBasicBlock* pBB = GetBB(0); (pBB != NULL); pBB = pBB->pNextBB)
1700+
{
1701+
INTERP_DUMP("BB:%d has overlappingEHClauseCount=%d and ilOffset=%x\n", pBB->index, pBB->overlappingEHClauseCount, pBB->ilOffset);
1702+
}
1703+
}
1704+
#endif
1705+
16851706
for (unsigned int i = 0; i < getEHcount(m_methodInfo); i++)
16861707
{
16871708
CORINFO_EH_CLAUSE clause;
@@ -2272,8 +2293,9 @@ void InterpCompiler::CreateLeaveChainIslandBasicBlocks(CORINFO_METHOD_INFO* meth
22722293

22732294
if (pLeaveChainIslandBB == NULL)
22742295
{
2275-
pLeaveChainIslandBB = AllocBB(clause.HandlerOffset + clause.HandlerLength);
2296+
pLeaveChainIslandBB = AllocBB(clause.HandlerOffset);
22762297
pLeaveChainIslandBB->pLeaveTargetBB = pLeaveTargetBB;
2298+
pLeaveChainIslandBB->isLeaveChainIsland = true;
22772299
*ppLastBBNext = pLeaveChainIslandBB;
22782300
}
22792301

src/coreclr/interpreter/compiler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ struct InterpBasicBlock
335335
// Valid only for BBs of call islands. It is set to true if it is a finally call island, false if is is a catch leave island.
336336
bool isFinallyCallIsland;
337337

338+
// Is a leave chain island basic block
339+
bool isLeaveChainIsland;
340+
338341
// If this basic block is a catch or filter funclet entry, this is the index of the variable
339342
// that holds the exception object.
340343
int clauseVarIndex;
@@ -366,6 +369,7 @@ struct InterpBasicBlock
366369
clauseType = BBClauseNone;
367370
isFilterOrCatchFuncletEntry = false;
368371
isFinallyCallIsland = false;
372+
isLeaveChainIsland = false;
369373
clauseVarIndex = -1;
370374
overlappingEHClauseCount = 0;
371375
enclosingTryBlockCount = -1;

0 commit comments

Comments
 (0)