Skip to content

Commit

Permalink
fuzzgen: Use Switch interface
Browse files Browse the repository at this point in the history
Turns out this is an interface that the frontend provides.
We should fuzz it.
  • Loading branch information
afonso360 committed Jul 21, 2022
1 parent fd639dd commit e23388e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
10 changes: 10 additions & 0 deletions cranelift/fuzzgen/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@ pub struct Config {
/// This value does not apply to block0 which takes the function params
/// and is thus governed by `signature_params`
pub block_signature_params: RangeInclusive<usize>,
/// Max number of jump tables generated per function
/// Note, the actual number of jump tables may be larger if the Switch interface
/// decides to insert more.
pub jump_tables_per_function: RangeInclusive<usize>,
pub jump_table_entries: RangeInclusive<usize>,
/// The Switch API specializes either individual blocks or contiguous ranges.
/// In `switch_cases` we decide to produce either a single block or a range.
/// The size of the range is controlled by `switch_max_range_size`.
pub switch_cases: RangeInclusive<usize>,
pub switch_max_range_size: RangeInclusive<usize>,

/// Stack slots.
/// The combination of these two determines stack usage per function
Expand All @@ -38,6 +46,8 @@ impl Default for Config {
block_signature_params: 0..=16,
jump_tables_per_function: 0..=4,
jump_table_entries: 0..=16,
switch_cases: 0..=64,
switch_max_range_size: 0..=32,
static_stack_slots_per_function: 0..=8,
static_stack_slot_size: 0..=128,
}
Expand Down
45 changes: 44 additions & 1 deletion cranelift/fuzzgen/src/function_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ use cranelift::codegen::ir::{
AbiParam, Block, ExternalName, Function, JumpTable, Opcode, Signature, StackSlot, Type, Value,
};
use cranelift::codegen::isa::CallConv;
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
use cranelift::prelude::{
EntityRef, InstBuilder, IntCC, JumpTableData, StackSlotData, StackSlotKind,
};
use std::collections::HashMap;
use std::ops::RangeInclusive;

type BlockSignature = Vec<Type>;
Expand Down Expand Up @@ -454,6 +455,47 @@ where
Ok(())
}

fn generate_switch(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
let _type = *self.u.choose(
&[
I8, I16, I32, I64, // TODO: I128
][..],
)?;
let switch_var = self.get_variable_of_type(_type)?;
let switch_val = builder.use_var(switch_var);

let valid_blocks = self.generate_valid_jumptable_target_blocks();
let default_block = *self.u.choose(&valid_blocks[..])?;

// Build this into a HashMap since we cannot have duplicate entries.
let mut entries = HashMap::new();
for _ in 0..self.param(&self.config.switch_cases)? {
// We can either insert a contiguous range of blocks or a individual block
// This is done because the Switch API specializes contiguous ranges.
if bool::arbitrary(self.u)? {
let index = self.u.arbitrary()?;
let block = *self.u.choose(&valid_blocks[..])?;
entries.insert(index, block);
} else {
let range_start: u128 = self.u.arbitrary()?;
let range_size = self.param(&self.config.switch_max_range_size)? as u128;
for i in 0..=range_size {
let index = range_start.wrapping_add(i);
let block = *self.u.choose(&valid_blocks[..])?;
entries.insert(index, block);
}
}
}

let mut switch = Switch::new();
for (entry, block) in entries.into_iter() {
switch.set_entry(entry, block);
}
switch.emit(builder, switch_val, default_block);

Ok(())
}

/// We always need to exit safely out of a block.
/// This either means a jump into another block or a return.
fn finalize_block(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
Expand All @@ -464,6 +506,7 @@ where
Self::generate_br_table,
Self::generate_jump,
Self::generate_return,
Self::generate_switch,
][..],
)?;

Expand Down

0 comments on commit e23388e

Please sign in to comment.