fuzzbug fix

This commit is contained in:
Chris Fallin 2021-12-24 11:42:02 -08:00
parent 1bd6b25d34
commit 80f7fc8a6c
4 changed files with 28 additions and 63 deletions

View file

@ -155,12 +155,7 @@ pub fn produce_func_wasm(f: &FunctionBody, body: &SerializedBody, locations: &Lo
wasm.locals wasm.locals
.extend(locations.new_locals.iter().map(|ty| ty_to_valty(*ty))); .extend(locations.new_locals.iter().map(|ty| ty_to_valty(*ty)));
let mut next_delete = 0; for operator in &body.operators {
for (index, operator) in body.operators.iter().enumerate() {
if next_delete < locations.delete.len() && locations.delete[next_delete] == index {
next_delete += 1;
continue;
}
wasm.translate(operator, locations); wasm.translate(operator, locations);
} }

View file

@ -9,7 +9,6 @@ use super::{SerializedBody, SerializedOperator};
#[derive(Debug)] #[derive(Debug)]
pub struct Locations { pub struct Locations {
pub locations: FxHashMap<(Value, usize), LocalId>, pub locations: FxHashMap<(Value, usize), LocalId>,
pub delete: Vec<usize>,
pub new_locals: Vec<wasmparser::Type>, pub new_locals: Vec<wasmparser::Type>,
} }
@ -42,7 +41,6 @@ impl Locations {
pub fn compute(f: &FunctionBody, body: &SerializedBody) -> Locations { pub fn compute(f: &FunctionBody, body: &SerializedBody) -> Locations {
let mut locations = Locations { let mut locations = Locations {
locations: FxHashMap::default(), locations: FxHashMap::default(),
delete: vec![],
new_locals: vec![], new_locals: vec![],
}; };
let mut allocator = Allocator { let mut allocator = Allocator {
@ -54,7 +52,7 @@ impl Locations {
ends: vec![], ends: vec![],
}; };
allocator.compute_spans_and_deleted_ops(&body.operators[..]); allocator.compute_spans(&body.operators[..]);
locations locations
} }
@ -73,6 +71,14 @@ impl<'a> Allocator<'a> {
}, },
); );
log::trace!(
"handle_op: at location {} op {:?} reads {:?} writes {:?}",
location,
op,
reads,
writes
);
for (value, index) in reads { for (value, index) in reads {
let span = match self.spans.get_mut(&(value, index)) { let span = match self.spans.get_mut(&(value, index)) {
Some(span) => span, Some(span) => span,
@ -81,64 +87,24 @@ impl<'a> Allocator<'a> {
} }
}; };
span.end = location + 1; span.end = location + 1;
log::trace!(" -> span for {}: {:?}", value, span);
} }
for (value, index) in writes { for (value, index) in writes {
self.spans let span = self.spans.entry((value, index)).or_insert(ValueSpan {
.entry((value, index))
.or_insert(ValueSpan {
value, value,
multi_value_index: index, multi_value_index: index,
start: location, start: location,
end: location + 1, end: location + 1,
}) });
.end = location + 1; span.end = location + 1;
log::trace!(" -> span for {}: {:?}", value, span);
} }
} }
fn compute_spans_and_deleted_ops(&mut self, operators: &[SerializedOperator]) { fn compute_spans(&mut self, operators: &[SerializedOperator]) {
// Delete runs of Set(A), Set(B), Get(B), Get(A): these are // For each operator, get the reads and writes and construct spans.
// stack-neutral sequences.
let mut start = None;
let mut current_run = vec![];
for (index, operator) in operators.iter().enumerate() { for (index, operator) in operators.iter().enumerate() {
match operator {
&SerializedOperator::Set(..) if start.is_none() => {
start = Some(index);
current_run.push(operator.clone());
}
&SerializedOperator::Set(..) => {
current_run.push(operator.clone());
}
&SerializedOperator::Get(v, i)
if start.is_some()
&& current_run.last() == Some(&SerializedOperator::Set(v, i)) =>
{
current_run.pop();
if current_run.is_empty() {
for i in start.unwrap()..=index {
self.locations.delete.push(i);
}
start = None;
}
}
_ => {
current_run.clear();
start = None;
}
}
}
// For each non-deleted operator, get the reads and writes and construct spans.
let mut next_delete = 0;
for (index, operator) in operators.iter().enumerate() {
if next_delete < self.locations.delete.len()
&& self.locations.delete[next_delete] == index
{
next_delete += 1;
continue;
}
self.handle_op(index, operator); self.handle_op(index, operator);
} }

View file

@ -400,6 +400,7 @@ impl<'a> SerializedBodyContext<'a> {
// Now push the args in reverse order. // Now push the args in reverse order.
for &arg in operands.iter().rev() { for &arg in operands.iter().rev() {
let arg = self.f.resolve_alias(arg);
match &self.f.values[arg.index()] { match &self.f.values[arg.index()] {
&ValueDef::Operator(op, ..) => { &ValueDef::Operator(op, ..) => {
if op_rematerialize(&op) { if op_rematerialize(&op) {

View file

@ -25,6 +25,7 @@ impl UseCountAnalysis {
for &value in &f.blocks[block].insts { for &value in &f.blocks[block].insts {
if value != Value::undef() { if value != Value::undef() {
let value = f.resolve_alias(value); let value = f.resolve_alias(value);
counts.add(value);
if workqueue_set.insert(value) { if workqueue_set.insert(value) {
workqueue.push_back(value); workqueue.push_back(value);
} }
@ -34,6 +35,7 @@ impl UseCountAnalysis {
f.blocks[block].terminator.visit_uses(|value| { f.blocks[block].terminator.visit_uses(|value| {
if value != Value::undef() { if value != Value::undef() {
let value = f.resolve_alias(value); let value = f.resolve_alias(value);
counts.add(value);
if workqueue_set.insert(value) { if workqueue_set.insert(value) {
workqueue.push_back(value); workqueue.push_back(value);
} }
@ -42,7 +44,6 @@ impl UseCountAnalysis {
while let Some(value) = workqueue.pop_front() { while let Some(value) = workqueue.pop_front() {
workqueue_set.remove(&value); workqueue_set.remove(&value);
counts.add(value);
match &f.values[value.index()] { match &f.values[value.index()] {
&ValueDef::Alias(..) | &ValueDef::Arg(..) | &ValueDef::BlockParam(..) => {} &ValueDef::Alias(..) | &ValueDef::Arg(..) | &ValueDef::BlockParam(..) => {}
&ValueDef::Operator(_op, ref args) => { &ValueDef::Operator(_op, ref args) => {
@ -51,7 +52,8 @@ impl UseCountAnalysis {
continue; continue;
} }
let arg = f.resolve_alias(arg); let arg = f.resolve_alias(arg);
if counts.use_count[arg.index()] == 0 { counts.add(arg);
if counts.use_count[arg.index()] == 1 {
if workqueue_set.insert(arg) { if workqueue_set.insert(arg) {
workqueue.push_back(arg); workqueue.push_back(arg);
} }
@ -63,7 +65,8 @@ impl UseCountAnalysis {
continue; continue;
} }
let value = f.resolve_alias(value); let value = f.resolve_alias(value);
if counts.use_count[value.index()] == 0 { counts.add(value);
if counts.use_count[value.index()] == 1 {
if workqueue_set.insert(value) { if workqueue_set.insert(value) {
workqueue.push_back(value); workqueue.push_back(value);
} }