varies-rust opened issue #13409:
Hello, and thank you for maintaining this crate.
I found a sanitizer/Miri failure reachable through public crate APIs using safe Rust code. I may be missing crate-specific preconditions, but the behavior looks worth checking because safe callers should not be able to trigger undefined behavior.
Summary
- Crate:
cranelift-egraph- Version tested:
0.91.1- API paths with similar failures observed:
BumpVec::pushBumpVec::reserveBumpVec::truncateBumpArena::singleBumpArena::vec_with_capacityObserved diagnostics
MemorySanitizer use of uninitialized value: WARNING: MemorySanitizer: use-of-uninitialized-value Miri undefined behavior: error: Undefined Behavior: reading memory at alloc68512[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memoryReproduction
The snippets below are minimal readable reproducers. Each PoC also includes the source location most relevant to the reported failure.
PoC 1:
test_cranelift_egraph109::generated_test_109Relevant source location:
src/bumpvec.rs:357:BumpVec::pushaccepts an arbitraryBumpArena<T>argument.src/bumpvec.rs:304:as_slicereads from the supplied arena using only storedbaseandlen.Readable equivalent PoC:
use std::io::Sink; #[test] fn poc() { let mut vec = cranelift_egraph::BumpVec::<&Sink>::default(); let mut arena_b = cranelift_egraph::BumpArena::<&Sink>::default(); let sink = std::io::sink(); vec.push(&sink, &mut arena_b); let mut arena_a = cranelift_egraph::BumpArena::<&Sink>::default(); let _ = arena_a.vec_with_capacity(1); let _ = vec.as_slice(&arena_a)[0]; }Observed diagnostic:
WARNING: MemorySanitizer: use-of-uninitialized-valuePoC 2:
test_cranelift_egraph120::generated_test_120Relevant source location:
src/bumpvec.rs:334:reservealso accepts an arbitrary arena argument.src/bumpvec.rs:357:pushcan attach data through a different arena than later operations use.Readable equivalent PoC:
use std::io::Sink; #[test] fn poc() { let mut vec = cranelift_egraph::BumpVec::<&Sink>::default(); let mut arena_b = cranelift_egraph::BumpArena::<&Sink>::default(); let sink = std::io::sink(); vec.push(&sink, &mut arena_b); let mut arena_a = cranelift_egraph::BumpArena::<&Sink>::default(); let _ = arena_a.vec_with_capacity(2); vec.reserve(1, &mut arena_a); }Observed diagnostic:
error: Undefined Behavior: reading memory at alloc68512[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memorySource review and suggested fix
Brief reasoning:
BumpVectracks only numeric indices, not the arena that actually owns the backing slots.- A safe caller can push into one arena and later read or reallocate the same logical vector through another arena.
- That breaks the storage provenance the unsafe helpers rely on.
Suggested fix:
- Tie the vector to the arena lifetime or store and check arena identity before using arena-backed storage.
Thanks again for taking a look.
varies-rust added the bug label to Issue #13409.
varies-rust added the cranelift label to Issue #13409.
cfallin commented on issue #13409:
Hi:
cranelift-egraphis no longer maintained -- we merged the egraph implementation back into our existingcranelift-codegencrate long ago. The old crate version still on crates.io is an artifact of our project setup with multiple crates: when we delete a crate, we no longer publish new versions with new Cranelift/Wasmtime releases, so an old version remains forever on crates.io.Maybe we should change that (e.g. publish a "tombstone" version that is empty, or yank the crate). @fitzgen @alexcrichton what do you think?
fitzgen commented on issue #13409:
Either seems fine by me. Also doing nothing is probably also fine, since this is the first spurious report we've had in many years of that crate not being active.
alexcrichton commented on issue #13409:
Personally I'd say we do nothing here, there's a fair number of
wasmtime-*crates that are no longer maintained and I don't know the set that we'd have to go back and publish markers for.
cfallin closed issue #13409:
Hello, and thank you for maintaining this crate.
I found a sanitizer/Miri failure reachable through public crate APIs using safe Rust code. I may be missing crate-specific preconditions, but the behavior looks worth checking because safe callers should not be able to trigger undefined behavior.
Summary
- Crate:
cranelift-egraph- Version tested:
0.91.1- API paths with similar failures observed:
BumpVec::pushBumpVec::reserveBumpVec::truncateBumpArena::singleBumpArena::vec_with_capacityObserved diagnostics
MemorySanitizer use of uninitialized value: WARNING: MemorySanitizer: use-of-uninitialized-value Miri undefined behavior: error: Undefined Behavior: reading memory at alloc68512[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memoryReproduction
The snippets below are minimal readable reproducers. Each PoC also includes the source location most relevant to the reported failure.
PoC 1:
test_cranelift_egraph109::generated_test_109Relevant source location:
src/bumpvec.rs:357:BumpVec::pushaccepts an arbitraryBumpArena<T>argument.src/bumpvec.rs:304:as_slicereads from the supplied arena using only storedbaseandlen.Readable equivalent PoC:
use std::io::Sink; #[test] fn poc() { let mut vec = cranelift_egraph::BumpVec::<&Sink>::default(); let mut arena_b = cranelift_egraph::BumpArena::<&Sink>::default(); let sink = std::io::sink(); vec.push(&sink, &mut arena_b); let mut arena_a = cranelift_egraph::BumpArena::<&Sink>::default(); let _ = arena_a.vec_with_capacity(1); let _ = vec.as_slice(&arena_a)[0]; }Observed diagnostic:
WARNING: MemorySanitizer: use-of-uninitialized-valuePoC 2:
test_cranelift_egraph120::generated_test_120Relevant source location:
src/bumpvec.rs:334:reservealso accepts an arbitrary arena argument.src/bumpvec.rs:357:pushcan attach data through a different arena than later operations use.Readable equivalent PoC:
use std::io::Sink; #[test] fn poc() { let mut vec = cranelift_egraph::BumpVec::<&Sink>::default(); let mut arena_b = cranelift_egraph::BumpArena::<&Sink>::default(); let sink = std::io::sink(); vec.push(&sink, &mut arena_b); let mut arena_a = cranelift_egraph::BumpArena::<&Sink>::default(); let _ = arena_a.vec_with_capacity(2); vec.reserve(1, &mut arena_a); }Observed diagnostic:
error: Undefined Behavior: reading memory at alloc68512[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memorySource review and suggested fix
Brief reasoning:
BumpVectracks only numeric indices, not the arena that actually owns the backing slots.- A safe caller can push into one arena and later read or reallocate the same logical vector through another arena.
- That breaks the storage provenance the unsafe helpers rely on.
Suggested fix:
- Tie the vector to the arena lifetime or store and check arena identity before using arena-backed storage.
Thanks again for taking a look.
cfallin commented on issue #13409:
Cool, I will close the issue then, on the basis that the version of Wasmtime+Cranelift that that crate is associated with is far outside of our current support window. Thanks nevertheless for filing the issue!
Last updated: Jun 01 2026 at 09:49 UTC