Fixed stackifier fuzzbug

This commit is contained in:
Chris Fallin 2021-11-20 12:20:34 -08:00
parent b84509c938
commit ca0570c0d0
3 changed files with 24 additions and 2 deletions

View file

@ -13,6 +13,7 @@ cargo-fuzz = true
libfuzzer-sys = "0.4" libfuzzer-sys = "0.4"
wasm-smith = "0.8" wasm-smith = "0.8"
env_logger = "0.9" env_logger = "0.9"
log = "0.4"
[dependencies.waffle] [dependencies.waffle]
path = ".." path = ".."

View file

@ -5,6 +5,7 @@ use waffle::Module;
fuzz_target!(|module: wasm_smith::Module| { fuzz_target!(|module: wasm_smith::Module| {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
log::debug!("original module: {:?}", module);
let orig_bytes = module.to_bytes(); let orig_bytes = module.to_bytes();
let parsed_module = Module::from_wasm_bytes(&orig_bytes[..]).unwrap(); let parsed_module = Module::from_wasm_bytes(&orig_bytes[..]).unwrap();
let _ = parsed_module.to_wasm_bytes(); let _ = parsed_module.to_wasm_bytes();

View file

@ -1,6 +1,7 @@
//! IR-to-Wasm transform. //! IR-to-Wasm transform.
use crate::{cfg::CFGInfo, ir::*}; use crate::{cfg::CFGInfo, ir::*};
use log::debug;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Shape { pub enum Shape {
@ -13,7 +14,7 @@ pub enum Shape {
/// Index in RPO. /// Index in RPO.
type OrderedBlockId = usize; type OrderedBlockId = usize;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Region { enum Region {
/// Forward-branch region. Extends from end (just prior to /// Forward-branch region. Extends from end (just prior to
/// terminator) of first block to just before second block. Can be /// terminator) of first block to just before second block. Can be
@ -78,10 +79,14 @@ impl Region {
} }
impl Shape { impl Shape {
pub fn compute(_f: &FunctionBody, cfg: &CFGInfo) -> Self { pub fn compute(f: &FunctionBody, cfg: &CFGInfo) -> Self {
// Process all non-contiguous edges in RPO block order. For // Process all non-contiguous edges in RPO block order. For
// forward and backward edges, emit Regions. // forward and backward edges, emit Regions.
debug!("f = {:?}", f);
debug!("cfg = {:?}", cfg);
let order = cfg.rpo(); let order = cfg.rpo();
debug!("rpo = {:?}", order);
assert_eq!(order[0], 0); // Entry block should come first. assert_eq!(order[0], 0); // Entry block should come first.
let mut regions = vec![]; let mut regions = vec![];
for (block_pos, &block) in order.iter().enumerate() { for (block_pos, &block) in order.iter().enumerate() {
@ -102,6 +107,7 @@ impl Shape {
// regions where necessary and duplicating where we find // regions where necessary and duplicating where we find
// irreducible control flow. // irreducible control flow.
regions.sort_by_key(|r| r.start()); regions.sort_by_key(|r| r.start());
debug!("regions = {:?}", regions);
// Examine each region in the sequence, determining whether it // Examine each region in the sequence, determining whether it
// is properly nested with respect to all overlapping regions. // is properly nested with respect to all overlapping regions.
@ -110,16 +116,23 @@ impl Shape {
i += 1; i += 1;
let prev = regions[i - 1]; let prev = regions[i - 1];
let this = regions[i]; let this = regions[i];
debug!("examining: {:?} -> {:?}", prev, this);
if !prev.overlaps(&this) { if !prev.overlaps(&this) {
debug!(" -> no overlap");
continue; continue;
} }
match (prev, this) { match (prev, this) {
(a, b) if a == b => {
regions.remove(i);
i -= 1;
}
(Region::Backward(a, b), Region::Backward(c, d)) if a == c => { (Region::Backward(a, b), Region::Backward(c, d)) if a == c => {
// Merge by extending end. // Merge by extending end.
regions[i - 1] = Region::Backward(a, std::cmp::max(b, d)); regions[i - 1] = Region::Backward(a, std::cmp::max(b, d));
regions.remove(i); regions.remove(i);
i -= 1;
} }
(Region::Backward(a, b), Region::Backward(c, _d)) if a < c && c <= b => { (Region::Backward(a, b), Region::Backward(c, _d)) if a < c && c <= b => {
panic!("Irreducible CFG"); panic!("Irreducible CFG");
@ -137,6 +150,7 @@ impl Shape {
// Merge. // Merge.
regions[i - 1] = Region::Forward(std::cmp::min(a, c), b); regions[i - 1] = Region::Forward(std::cmp::min(a, c), b);
regions.remove(i); regions.remove(i);
i -= 1;
} }
(Region::Forward(a, b), Region::Forward(c, d)) if a <= c && b < d => { (Region::Forward(a, b), Region::Forward(c, d)) if a <= c && b < d => {
regions[i - 1] = Region::Forward(a, d); regions[i - 1] = Region::Forward(a, d);
@ -146,6 +160,8 @@ impl Shape {
} }
} }
debug!("after stackifying: {:?}", regions);
// Ensure the regions properly nest. // Ensure the regions properly nest.
let mut stack: Vec<Region> = vec![]; let mut stack: Vec<Region> = vec![];
for region in &regions { for region in &regions {
@ -167,6 +183,10 @@ impl Shape {
} }
} }
// TODO: make regions properly nest by doing replication right
// as we compute the RPO. Track the current nesting, and
// traverse more than once if needed.
Shape::None Shape::None
} }
} }