owl 0.0.3

ROP-gadget finder in Rust
use error::*;
use falcon_capstone::capstone;
use Gadget;
use rayon::prelude::*;


pub(crate) fn find(
    address: u64,
    bytes: &[u8],
    depth: usize,
    minimum_instruction_width: usize,
    arch: capstone::cs_arch,
    mode: capstone::cs_mode,
    ret_instructions: &[capstone::InstrIdArch],
    valid_instructions: &[capstone::InstrIdArch],
    delay_slot: usize
) -> Result<Vec<Gadget>> {

    let gadgets = (0..bytes.len() / minimum_instruction_width)
        .into_par_iter()
        .fold(|| Vec::new(), |mut gadgets, offset| {

            let offset = offset * minimum_instruction_width;

            let cs = capstone::Capstone::new(arch, mode)
                .expect("Failed to instantiate capstone");

            'depth: for _ in 0..depth {
                let top = if offset + depth > bytes.len() {
                    bytes.len()
                } else {
                    offset + depth
                };
                let disassembly_range = offset..top;
                let disassembly_bytes = bytes.get(disassembly_range).unwrap();
                let instructions = match cs.disasm(disassembly_bytes,
                                                address + offset as u64,
                                                depth) {
                    Ok(instructions) => instructions,
                    Err(_) => continue
                };

                let mut instrs: Vec<String> = Vec::new();

                let mut length: usize = 0;

                for instruction in instructions.iter() {
                    length += instruction.size as usize;
                    instrs.push(format!("{} {}", instruction.mnemonic, instruction.op_str));

                    if ret_instructions.contains(&instruction.id) {
                        let bytes =
                            match disassembly_bytes.get(0..(length + delay_slot)) {
                                Some(bytes) => bytes,
                                None => { continue; }
                            };
                        gadgets.push(Gadget::new(offset as u64, instrs, bytes.to_vec()));
                        break 'depth;
                    }
                    else if !valid_instructions.contains(&instruction.id) {
                        break;
                    }
                }
            }
            gadgets
        })
        .reduce(|| Vec::new(), |mut a, mut b| {
            a.append(&mut b);
            a
        });

    Ok(gadgets)
}