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"
wasm-smith = "0.8"
env_logger = "0.9"
log = "0.4"
[dependencies.waffle]
path = ".."

View file

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

View file

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