From 0ff49b9614311456def2f15748b7341efa0bf731 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sun, 3 May 2026 09:40:23 +0100 Subject: [PATCH] add a test demonstrating double-free in extend() for ZSTs --- tests/tests.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/tests.rs b/tests/tests.rs index ff779ba..098614b 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -716,6 +716,32 @@ fn test_extend_zst() { assert_eq!(array.len(), 5); } +#[test] +fn test_extend_zst_with_drop_is_not_dropped_twice_via_safe_api() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static DROP_COUNT: AtomicUsize = AtomicUsize::new(0); + + struct ZstWithSafeDrop; + + impl Drop for ZstWithSafeDrop { + fn drop(&mut self) { + let previous = DROP_COUNT.fetch_add(1, Ordering::SeqCst); + // Extending with a single ZST moves one logical value into the ArrayVec. + // Its Drop implementation must run exactly once, when the ArrayVec drops. + if previous != 0 { + panic!("ZST value dropped more than once"); + } + } + } + + DROP_COUNT.store(0, Ordering::SeqCst); + + let mut vec = ArrayVec::::new(); + vec.extend(std::iter::once(ZstWithSafeDrop)); + drop(vec); +} + #[test] fn test_try_from_argument() { use core::convert::TryFrom;