Listen to this Post
The vulnerability stems from a panic safety flaw in the `InlineVec::clear()` and `SerVec::clear()` methods of the rkyv crate. Both functions iterated over their elements, calling `drop_in_place` on each to free the element’s memory, but only updated the container’s internal length (self.len) after the entire loop completed. This order-of-operations bug creates a critical window: if an element’s `Drop` implementation (e.g., for a struct holding a Box<T>) panics during this iteration, the loop is aborted, and `self.len` is never updated, remaining at its original value. The container is now in an inconsistent state where it believes it still owns `n` elements, but some elements have already been dropped and freed.
A second, subsequent call to `clear()` on the same container will then re-enter the cleanup logic and iterate over those already-freed memory locations, leading to a double-free condition. This second call can occur in two specific ways. For InlineVec, it is invoked again from its own `Drop` implementation when the vector goes out of scope. For SerVec, the second `clear()` is called by `SerVec::with_capacity()` after a user-supplied closure returns. The technical impact includes CWE-415 (Double Free), causing heap corruption, and CWE-416 (Use-After-Free), leading to memory corruption. Critically, this entire attack chain is triggerable from safe Rust code using `std::panic::catch_unwind` and requires no special privileges, making it a severe logical flaw in a foundational memory safety crate.
dailycve form:
Platform: rkyv crate
Version: 0.8.0-0.8.15
Vulnerability: Panic safety
Severity: Moderate
date: 2026-05-15
Prediction: 2026-05-16
Analytics under What Undercode Say:
Check rkyv version
grep ‘rkyv’ Cargo.toml
Output: rkyv = { version = “0.8.15” }
Update to patched version
cargo update -p rkyv –precise 0.8.16
Simulate vulnerability with Miri
cargo +nightly miri test — –nocapture
Exploit:
use std::panic::catch_unwind;
use rkyv::util::InlineVec;
struct PanicOnDrop;
impl Drop for PanicOnDrop {
fn drop(&mut self) { panic!("panic in drop"); }
}
fn main() {
let mut vec: InlineVec<PanicOnDrop, 4> = InlineVec::new();
vec.push(PanicOnDrop);
let _ = catch_unwind(move || {
vec.clear(); // First clear triggers panic
});
// Subsequent clear of already-freed elements occurs in Drop
}
Protection from this CVE:
Upgrade to rkyv version 0.8.16 immediately. The patch restructures the `clear()` function to update the container’s length (self.len) before starting the iteration that calls drop_in_place, eliminating the inconsistent state. Avoid using `std::panic::catch_unwind` around unsafe memory containers. Review any custom `Drop` implementations for panics.
Impact:
Memory corruption leading to arbitrary code execution (ACE). Attackers can trigger double-frees or use-after-free conditions, potentially hijacking control flow or leaking sensitive information. Denial of service (DoS) is also possible. No privileges are required, and the attack is fully remote if the vulnerable code processes untrusted input.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

