From 81d5781e6cbe67141f800fea7f0e4cd6ef2ce240 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Wed, 1 Sep 2021 23:25:40 +0100 Subject: [PATCH] cranelift: CLIF fuzzer generate jump tables and br_table --- cranelift/fuzzgen/src/config.rs | 4 ++ cranelift/fuzzgen/src/function_generator.rs | 50 ++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/cranelift/fuzzgen/src/config.rs b/cranelift/fuzzgen/src/config.rs index b52918069d..458a6fd330 100644 --- a/cranelift/fuzzgen/src/config.rs +++ b/cranelift/fuzzgen/src/config.rs @@ -16,6 +16,8 @@ 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, + pub jump_tables_per_function: RangeInclusive, + pub jump_table_entries: RangeInclusive, } impl Default for Config { @@ -28,6 +30,8 @@ impl Default for Config { vars_per_function: 0..=16, blocks_per_function: 0..=16, block_signature_params: 0..=16, + jump_tables_per_function: 0..=4, + jump_table_entries: 0..=16, } } } diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs index acb801be8c..0814ac72ac 100644 --- a/cranelift/fuzzgen/src/function_generator.rs +++ b/cranelift/fuzzgen/src/function_generator.rs @@ -3,11 +3,11 @@ use anyhow::Result; use arbitrary::{Arbitrary, Unstructured}; use cranelift::codegen::ir::types::*; use cranelift::codegen::ir::{ - AbiParam, Block, ExternalName, Function, Opcode, Signature, Type, Value, + AbiParam, Block, ExternalName, Function, JumpTable, Opcode, Signature, Type, Value, }; use cranelift::codegen::isa::CallConv; use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; -use cranelift::prelude::{EntityRef, InstBuilder, IntCC}; +use cranelift::prelude::{EntityRef, InstBuilder, IntCC, JumpTableData}; use std::ops::RangeInclusive; type BlockSignature = Vec; @@ -98,6 +98,7 @@ where config: &'r Config, vars: Vec<(Type, Variable)>, blocks: Vec<(Block, BlockSignature)>, + jump_tables: Vec, } impl<'r, 'data> FunctionGenerator<'r, 'data> @@ -110,6 +111,7 @@ where config, vars: vec![], blocks: vec![], + jump_tables: vec![], } } @@ -235,6 +237,16 @@ where Ok((block, args)) } + /// Valid blocks for jump tables have to have no parameters in the signature, and must also + /// not be the first block. + fn generate_valid_jumptable_target_blocks(&mut self) -> Vec { + self.blocks[1..] + .iter() + .filter(|(_, sig)| sig.len() == 0) + .map(|(b, _)| *b) + .collect() + } + fn generate_values_for_signature>( &mut self, builder: &mut FunctionBuilder, @@ -266,6 +278,20 @@ where Ok(()) } + /// Generates a br_table into a random block + fn generate_br_table(&mut self, builder: &mut FunctionBuilder) -> Result<()> { + let _type = *self.u.choose(&[I8, I16, I32, I64][..])?; + let var = self.get_variable_of_type(_type)?; + let val = builder.use_var(var); + + let valid_blocks = self.generate_valid_jumptable_target_blocks(); + let default_block = *self.u.choose(&valid_blocks[..])?; + + let jt = *self.u.choose(&self.jump_tables[..])?; + builder.ins().br_table(val, default_block, jt); + Ok(()) + } + /// Generates a brz/brnz into a random block fn generate_br(&mut self, builder: &mut FunctionBuilder) -> Result<()> { let (block, args) = self.generate_target_block(builder)?; @@ -320,6 +346,7 @@ where &[ Self::generate_bricmp, Self::generate_br, + Self::generate_br_table, Self::generate_jump, Self::generate_return, ][..], @@ -338,6 +365,22 @@ where Ok(()) } + fn generate_jumptables(&mut self, builder: &mut FunctionBuilder) -> Result<()> { + let valid_blocks = self.generate_valid_jumptable_target_blocks(); + + for _ in 0..self.param(&self.config.jump_tables_per_function)? { + let mut jt_data = JumpTableData::new(); + + for _ in 0..self.param(&self.config.jump_table_entries)? { + let block = *self.u.choose(&valid_blocks[..])?; + jt_data.push_entry(block); + } + + self.jump_tables.push(builder.create_jump_table(jt_data)); + } + Ok(()) + } + /// Creates a random amount of blocks in this function fn generate_blocks( &mut self, @@ -422,6 +465,9 @@ where self.blocks = self.generate_blocks(&mut builder, &sig)?; + // Function preamble + self.generate_jumptables(&mut builder)?; + // Main instruction generation loop for (i, (block, block_sig)) in self.blocks.clone().iter().enumerate() { let is_block0 = i == 0;