mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Fix for switches in infinite loop decompiler bug
This commit is contained in:
parent
0a0b716266
commit
efabf89ea2
3 changed files with 10 additions and 5 deletions
|
@ -1767,8 +1767,9 @@ BlockInfLoop *BlockGraph::newBlockInfLoop(FlowBlock *body)
|
|||
|
||||
/// Add the new BlockSwitch to \b this, collapsing all the case FlowBlocks into it.
|
||||
/// \param cs is the list of case FlowBlocks
|
||||
/// \param hasExit is \b true if the switch has a formal exit
|
||||
/// \return the new BlockSwitch
|
||||
BlockSwitch *BlockGraph::newBlockSwitch(const vector<FlowBlock *> &cs)
|
||||
BlockSwitch *BlockGraph::newBlockSwitch(const vector<FlowBlock *> &cs,bool hasExit)
|
||||
|
||||
{
|
||||
FlowBlock *rootbl = cs[0];
|
||||
|
@ -1779,6 +1780,8 @@ BlockSwitch *BlockGraph::newBlockSwitch(const vector<FlowBlock *> &cs)
|
|||
ret->grabCaseBasic(leafbl->subBlock(0),cs); // Must be called before the identifyInternal
|
||||
identifyInternal(ret,cs);
|
||||
addBlock(ret);
|
||||
if (hasExit)
|
||||
ret->forceOutputNum(1); // If there is an exit, there should be exactly 1 out edge
|
||||
ret->clearFlag(f_switch_out); // Don't consider this as being a switch "out"
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -326,7 +326,7 @@ public:
|
|||
BlockWhileDo *newBlockWhileDo(FlowBlock *cond,FlowBlock *cl); ///< Build a new BlockWhileDo
|
||||
BlockDoWhile *newBlockDoWhile(FlowBlock *condcl); ///< Build a new BlockDoWhile
|
||||
BlockInfLoop *newBlockInfLoop(FlowBlock *body); ///< Build a new BlockInfLoop
|
||||
BlockSwitch *newBlockSwitch(const vector<FlowBlock *> &cs); ///< Build a new BlockSwitch
|
||||
BlockSwitch *newBlockSwitch(const vector<FlowBlock *> &cs,bool hasExit); ///< Build a new BlockSwitch
|
||||
|
||||
void orderBlocks(void) { ///< Sort blocks using the final ordering
|
||||
if (list.size()!=1) sort(list.begin(),list.end(),compareFinalOrder); }
|
||||
|
|
|
@ -1636,7 +1636,10 @@ bool CollapseStructure::ruleBlockSwitch(FlowBlock *bl)
|
|||
// Find "obvious" exitblock, is sizeIn>1 or sizeOut>1
|
||||
for(int4 i=0;i<sizeout;++i) {
|
||||
FlowBlock *curbl = bl->getOut(i);
|
||||
if (curbl == bl) return false; // Cannot exit to itself (this can happen as a goto)
|
||||
if (curbl == bl) {
|
||||
exitblock = curbl; // Exit back to top of switch (loop)
|
||||
break;
|
||||
}
|
||||
if (curbl->sizeOut() > 1) {
|
||||
exitblock = curbl;
|
||||
break;
|
||||
|
@ -1673,7 +1676,6 @@ bool CollapseStructure::ruleBlockSwitch(FlowBlock *bl)
|
|||
if (exitblock->isGotoOut(i)) return false;
|
||||
for(int4 i=0;i<sizeout;++i) {
|
||||
FlowBlock *curbl = bl->getOut(i);
|
||||
if (curbl == bl) return false;
|
||||
if (curbl == exitblock) continue; // The switch can go straight to the exit block
|
||||
if (curbl->sizeIn() > 1) return false; // A case can only have the switch fall into it
|
||||
if (curbl->isGotoIn(0)) return false; // In cannot be a goto
|
||||
|
@ -1696,7 +1698,7 @@ bool CollapseStructure::ruleBlockSwitch(FlowBlock *bl)
|
|||
if (curbl == exitblock) continue; // Don't include exit as a case
|
||||
cases.push_back(curbl);
|
||||
}
|
||||
graph.newBlockSwitch(cases);
|
||||
graph.newBlockSwitch(cases,(exitblock != (FlowBlock *)0));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue