Skip to content

Copying collector incremental GC does not handle cancellation of GC operation #13516

@alexcrichton

Description

@alexcrichton

This input when run with this host:

use std::pin::Pin;
use std::task::{Context, Poll};
use wasmtime::*;

#[tokio::main]
async fn main() -> wasmtime::Result<()> {
    let mut config = Config::new();
    config.consume_fuel(true);
    config.wasm_gc(true);
    config.wasm_exceptions(true);
    config.wasm_function_references(true);
    let engine = Engine::new(&config)?;
    let mut store = Store::new(&engine, ());
    store.fuel_async_yield_interval(Some(85460))?;
    store.set_fuel(u64::MAX)?;

    let module = Module::from_file(&engine, "./hi.wat")?;
    let mut linker = Linker::new(&engine);
    linker.define_unknown_imports_as_default_values(&mut store, &module)?;
    let instance = linker.instantiate_async(&mut store, &module).await?;
    let f = instance.get_func(&mut store, "").unwrap();
    let mut rets = [Val::I32(0); 4];

    for _ in 0..2 {
        let _ = Timeout {
            future: f.call_async(&mut store, &[], &mut rets),
            polls: 5684,
        }
        .await;
    }
    Ok(())
}

struct Timeout<F> {
    future: F,
    polls: u32,
}

#[derive(Debug)]
enum Exhausted {
    Polls,
}

impl<F: Future> Future for Timeout<F> {
    type Output = Result<F::Output, Exhausted>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let (polls, future) = unsafe {
            let me = self.get_unchecked_mut();
            (&mut me.polls, Pin::new_unchecked(&mut me.future))
        };
        match future.poll(cx) {
            Poll::Ready(val) => Poll::Ready(Ok(val)),
            Poll::Pending => {
                if *polls == 0 {
                    log::warn!("future operation ran out of polls");
                    return Poll::Ready(Err(Exhausted::Polls));
                }
                *polls -= 1;
                Poll::Pending
            }
        }
    }
}

will panic:

$ RUSTFLAGS=--cfg=gc_zeal cargo run --bin repro
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
     Running `target/debug/repro`

thread 'main' (855450) panicked at crates/wasmtime/src/runtime/vm/gc/enabled/copying.rs:863:13:
newly allocated GC object at index 32784 is not fully poisoned; freed memory was corrupted
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Bisection shows #13491 as the culprit, cc @fitzgen

Metadata

Metadata

Assignees

Labels

fuzz-bugBugs found by a fuzzerwasm-proposal:gcIssues with the implementation of the gc wasm proposal

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions