From f2de1c8dbaa7fc418548697877813936ff5c6ef0 Mon Sep 17 00:00:00 2001 From: nuskey8 Date: Sun, 26 Jul 2026 15:12:36 +0900 Subject: [PATCH] fix: drop partially initialized array elements on decode errors --- zerompk/src/impl.rs | 24 ++++++++++++++++++++++++ zerompk/tests/deserialize.rs | 10 ++++++++++ 2 files changed, 34 insertions(+) diff --git a/zerompk/src/impl.rs b/zerompk/src/impl.rs index e1405c3..d8f3fe5 100644 --- a/zerompk/src/impl.rs +++ b/zerompk/src/impl.rs @@ -190,14 +190,38 @@ impl ToMessagePack for [T] { impl<'a, T: FromMessagePack<'a>, const N: usize> FromMessagePack<'a> for [T; N] { #[inline(always)] fn read>(reader: &mut R) -> crate::Result { + struct InitializedGuard { + ptr: *mut T, + initialized: usize, + } + + impl Drop for InitializedGuard { + fn drop(&mut self) { + // SAFETY: the first `initialized` elements were written + // exactly once, and the backing array still exists. + unsafe { + core::ptr::drop_in_place(core::ptr::slice_from_raw_parts_mut( + self.ptr, + self.initialized, + )); + } + } + } + reader.check_array_len(N)?; let mut arr: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit(); let ptr = arr.as_mut_ptr() as *mut T; + let mut guard = InitializedGuard { + ptr, + initialized: 0, + }; for i in 0..N { unsafe { ptr.add(i).write(T::read(reader)?); } + guard.initialized += 1; } + core::mem::forget(guard); Ok(unsafe { arr.assume_init() }) } } diff --git a/zerompk/tests/deserialize.rs b/zerompk/tests/deserialize.rs index 0d8afe9..121ae52 100644 --- a/zerompk/tests/deserialize.rs +++ b/zerompk/tests/deserialize.rs @@ -515,3 +515,13 @@ fn test_vec_drops_initialized_elements_on_decode_error() { assert!(error.is_err()); assert_eq!(PARTIAL_ARRAY_DROPS.load(Ordering::Relaxed), 1); } + +#[test] +fn test_fixed_array_drops_initialized_elements_on_decode_error() { + PARTIAL_ARRAY_DROPS.store(0, Ordering::Relaxed); + + let error = zerompk::from_msgpack::<[DropTracked; 2]>(&[0x92, 0x01, 0xc1]); + + assert!(error.is_err()); + assert_eq!(PARTIAL_ARRAY_DROPS.load(Ordering::Relaxed), 1); +}