Skip to content

Commit

Permalink
cranelift: Prevent infinite loops in ssa frontend with unreachable code.
Browse files Browse the repository at this point in the history
This issue was found by the CLIF fuzzer in bytecodealliance#3094.
  • Loading branch information
afonso360 committed Aug 27, 2021
1 parent 6fbddc1 commit 4786713
Showing 1 changed file with 70 additions and 5 deletions.
75 changes: 70 additions & 5 deletions cranelift/frontend/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,14 +278,16 @@ impl SSABuilder {
// This function is split into two parts to appease the borrow checker.
// Part 1: With a mutable borrow of self, update the DataFlowGraph if necessary.
let data = &mut self.ssa_blocks[block];

let case = if data.sealed {
// The block has multiple predecessors so we append a Block parameter that
// will serve as a value.
if data.predecessors.len() == 1 {
// Optimize the common case of one predecessor: no param needed.
// Optimize the common case of one predecessor: no param needed.
// Check if the block has itself as a predecessor, we need to insert a block param
// to handle that case.
if data.predecessors.len() == 1 && data.predecessors[0].block != block {
UseVarCases::SealedOnePredecessor(data.predecessors[0].block)
} else {
// Break potential cycles by eagerly adding an operandless param.
// The block has multiple predecessors so we append a Block parameter that
// will serve as a value.
let val = func.dfg.append_block_param(block, ty);
UseVarCases::SealedMultiplePredecessors(val, block)
}
Expand Down Expand Up @@ -1363,4 +1365,67 @@ mod tests {
}
}
}

#[test]
fn reassign_with_predecessor_loop_hangs() {
// Here is the pseudo-program we want to translate:
// block0:
// var0 = iconst 0
// jump block2;
// block1:
// jump block2;
// block2:
// ; phantom use of var0
// var0 = iconst 1
// jump block1;

let mut func = Function::new();
let mut ssa = SSABuilder::new();
let block0 = func.dfg.make_block();
let block1 = func.dfg.make_block();
let block2 = func.dfg.make_block();
let var0 = Variable::new(0);

{
let mut cur = FuncCursor::new(&mut func);
for block in [block0, block1, block2] {
cur.insert_block(block);
ssa.declare_block(block);
}
}

// block0
{
let mut cur = FuncCursor::new(&mut func).at_bottom(block0);

let var0_iconst = cur.ins().iconst(I32, 0);
ssa.def_var(var0, var0_iconst, block0);

let jump = cur.ins().jump(block2, &[]);
ssa.declare_block_predecessor(block2, block0, jump);
}

// block1
{
let mut cur = FuncCursor::new(&mut func).at_bottom(block1);

let jump = cur.ins().jump(block2, &[]);
ssa.declare_block_predecessor(block2, block1, jump);
}

// block2
{
let mut cur = FuncCursor::new(&mut func).at_bottom(block2);

let _ = ssa.use_var(&mut cur.func, var0, I32, block2).0;
let var0_iconst = cur.ins().iconst(I32, 1);
ssa.def_var(var0, var0_iconst, block2);

let jump = cur.ins().jump(block1, &[]);
ssa.declare_block_predecessor(block1, block1, jump);
}

// The sealing algorithm would enter a infinite loop here
ssa.seal_all_blocks(&mut func);
}
}

0 comments on commit 4786713

Please sign in to comment.