The following unit test, when placed in soa-rs-testing/src/lib.rs, causes miri to report a use-after-free:
mod ub_tests {
use super::*;
#[test]
fn append_clears_source_after_raw_move() {
// `Soa::append` raw-reads every element out of `other` and pushes those
// values into `self`, but it leaves `other.len` unchanged and then calls
// `other.clear()`. For owned fields, `clear` drops the stale source slot
// and frees the allocation that is now owned by `self`; miri reports UB
// when `self` later reads/drops the dangling owner.
#[derive(Soars)]
struct Owned {
value: Box<u8>,
}
let mut dst = Soa::<Owned>::new();
let mut src = soa![Owned {
value: Box::new(1),
}];
dst.append(&mut src);
}
}
You can reproduce it with cargo +nightly miri test --release --workspace
As a double free (or a use-after-free free, depending on how you look at it), this is a memory safety bug and may have security implications.
The issue was discovered by GPT-5.5 xhigh and verified manually before reporting.
The following unit test, when placed in
soa-rs-testing/src/lib.rs, causes miri to report a use-after-free:You can reproduce it with
cargo +nightly miri test --release --workspaceAs a double free (or a use-after-free free, depending on how you look at it), this is a memory safety bug and may have security implications.
The issue was discovered by GPT-5.5 xhigh and verified manually before reporting.