diff --git a/node-graph/libraries/core-types/src/attribute.rs b/node-graph/libraries/core-types/src/attribute.rs index f34a433439..13943668c9 100644 --- a/node-graph/libraries/core-types/src/attribute.rs +++ b/node-graph/libraries/core-types/src/attribute.rs @@ -154,10 +154,15 @@ pub struct AttributeInfo { pub write_stored: unsafe fn(&dyn AnyAttributeValue, *mut u8, &crate::arena::Arena) -> Option<()>, } +/// The default's object representation, staged through zeroed storage so a +/// value with padding or an unused payload (`Option`'s `None`) hands the +/// caller deterministic bytes rather than whatever the stack held. fn write_default_bytes(out: &mut [u8]) { assert_eq!(out.len(), size_of::>()); - let value: A::Value<'static> = A::default(); - unsafe { std::ptr::copy_nonoverlapping((&raw const value).cast::(), out.as_mut_ptr(), size_of::>()) }; + let mut staged = std::mem::MaybeUninit::>::zeroed(); + staged.write(A::default()); + // SAFETY: the staging holds a live value of the type `out` is sized for. + unsafe { std::ptr::copy_nonoverlapping(staged.as_ptr().cast::(), out.as_mut_ptr(), size_of::>()) }; } fn field_write_at(level: u8) -> crate::record::FieldWrite