Skip to content

Commit 29322bd

Browse files
committed
Add comprehensive safety comments to core plugin files
Added 57 safety comments across 3 critical files: plugin_base.rs: 18 comments - Plugin lifecycle management (GlobalSetup/Setdown, SequenceSetup/Setdown) - FFI entry points and callbacks - Sequence data management (Setup/Flatten/Unflatten) - Global data handle ownership transfer - Parameter array access during Render - AEGP plugin initialization lib.rs: 6 comments - PicaBasicSuite raw pointer dereferencing - Matrix4::as_slice() array to slice conversion - PointerOwnership Deref/DerefMut implementations - Raw pointer validity and lifetime requirements parameters.rs: 33 comments - Arbitrary data dispatch functions (NEW/DISPOSE/COPY/FLATTEN/etc) - Union field access based on param_type - Platform-specific string encoding (macOS CFString, Windows OEM) - Parameter value conversions (angle, color, point) - Memory safety for buffer operations - Handle lifecycle management Each comment documents: ✓ What invariants are being upheld ✓ Why the operation is safe ✓ What would cause undefined behavior Total safety comments across all files: 110+ (53 from previous commit + 57 new)
1 parent 96f867f commit 29322bd

3 files changed

Lines changed: 358 additions & 4 deletions

File tree

after-effects/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ impl PicaBasicSuite {
9494
#[inline]
9595
pub fn from_pr_in_data_raw(in_data_ptr: *const ae_sys::PR_InData) -> Self {
9696
Self {
97+
// SAFETY: The caller must guarantee that `in_data_ptr` is a valid, properly aligned,
98+
// non-null pointer to an initialized `PR_InData` struct that lives for the duration
99+
// of this access. The `PR_InData` struct is provided by After Effects during plugin
100+
// callbacks and remains valid for the callback's lifetime. Dereferencing violates
101+
// Rust's aliasing rules if the pointer is invalid, null, misaligned, or points to
102+
// uninitialized memory, resulting in undefined behavior.
97103
previous_pica_basic_suite_ptr: PicaBasicSuite::set(unsafe { *in_data_ptr }.pica_basicP),
98104
}
99105
}
@@ -102,6 +108,12 @@ impl PicaBasicSuite {
102108
pub fn from_pr_in_data(in_data_handle: pr::InDataHandle) -> Self {
103109
Self {
104110
previous_pica_basic_suite_ptr: PicaBasicSuite::set(
111+
// SAFETY: The `InDataHandle` is a wrapper around a pointer provided by After Effects.
112+
// We rely on `InDataHandle::as_ptr()` returning a valid, non-null, properly aligned
113+
// pointer to an initialized `PR_InData` struct. The handle ensures the data remains
114+
// valid for its lifetime. Dereferencing would be undefined behavior if the pointer
115+
// returned by `as_ptr()` is invalid, null, misaligned, dangling, or the underlying
116+
// data was already freed by After Effects.
105117
unsafe { *in_data_handle.as_ptr() }.pica_basicP,
106118
),
107119
}
@@ -110,6 +122,12 @@ impl PicaBasicSuite {
110122
#[inline]
111123
pub fn from_pf_in_data_raw(in_data_ptr: *const ae_sys::PF_InData) -> Self {
112124
Self {
125+
// SAFETY: The caller must guarantee that `in_data_ptr` is a valid, properly aligned,
126+
// non-null pointer to an initialized `PF_InData` struct that lives for the duration
127+
// of this access. The `PF_InData` struct is provided by After Effects during plugin
128+
// callbacks and remains valid for the callback's lifetime. Dereferencing violates
129+
// Rust's aliasing rules if the pointer is invalid, null, misaligned, or points to
130+
// uninitialized memory, resulting in undefined behavior.
113131
previous_pica_basic_suite_ptr: PicaBasicSuite::set(unsafe { *in_data_ptr }.pica_basicP),
114132
}
115133
}
@@ -263,6 +281,13 @@ impl From<ae_sys::A_Matrix4> for Matrix4 {
263281
impl Matrix4 {
264282
#[inline]
265283
pub fn as_slice(&self) -> &[f64] {
284+
// SAFETY: `Matrix4` is a `#[repr(C)]` struct containing `[[f64; 4]; 4]`, which is
285+
// guaranteed to be laid out as a contiguous array of 16 f64 values in memory.
286+
// `self.0.as_ptr()` returns a valid pointer to the start of this array, and we're
287+
// creating a slice of exactly 16 elements which matches the actual size. The returned
288+
// slice's lifetime is tied to `&self`, ensuring the data remains valid. This would be
289+
// undefined behavior if the length (16) exceeded the actual allocated size, if the
290+
// pointer was misaligned for f64, or if the data was uninitialized.
266291
unsafe { std::slice::from_raw_parts(self.0.as_ptr() as _, 16) }
267292
}
268293
}
@@ -614,6 +639,13 @@ impl<T> std::ops::Deref for PointerOwnership<T> {
614639
type Target = T;
615640
fn deref(&self) -> &Self::Target {
616641
match self {
642+
// SAFETY: When `PointerOwnership` is constructed with `AfterEffects(*mut T)`, the
643+
// caller must guarantee that the pointer is valid, properly aligned, non-null, and
644+
// points to a valid initialized `T` that remains valid for the lifetime of this
645+
// `PointerOwnership` instance. The returned reference's lifetime is tied to `&self`,
646+
// preventing use-after-free. This would be undefined behavior if the pointer is null,
647+
// dangling, misaligned, points to uninitialized memory, or if After Effects has
648+
// already freed the memory.
617649
Self::AfterEffects(ptr) => unsafe { &**ptr },
618650
Self::Rust(ptr) => ptr,
619651
}
@@ -622,6 +654,14 @@ impl<T> std::ops::Deref for PointerOwnership<T> {
622654
impl<T> std::ops::DerefMut for PointerOwnership<T> {
623655
fn deref_mut(&mut self) -> &mut T {
624656
match self {
657+
// SAFETY: When `PointerOwnership` is constructed with `AfterEffects(*mut T)`, the
658+
// caller must guarantee that the pointer is valid, properly aligned, non-null, and
659+
// points to a valid initialized `T` that remains valid and uniquely owned for the
660+
// lifetime of this `PointerOwnership` instance. The mutable reference's lifetime is
661+
// tied to `&mut self`, ensuring exclusive access and preventing aliasing violations.
662+
// This would be undefined behavior if the pointer is null, dangling, misaligned,
663+
// points to uninitialized memory, or if there are other active references to the
664+
// same memory (violating Rust's aliasing rules).
625665
Self::AfterEffects(ptr) => unsafe { &mut **ptr },
626666
Self::Rust(ptr) => ptr,
627667
}

0 commit comments

Comments
 (0)