From b92fe8401a3e710364ba88e51b4ac711cd42a9bb Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 30 Sep 2024 02:00:30 +0000 Subject: [PATCH] fix(transformer): `NonEmptyStack::push` write value before updating cursor (#6169) `NonEmptyStack::push` was previously updating `cursor` before writing the value to stack. This could be UB if the type `T` is `Drop`, and writing the value panicked - as then `drop` would attempt to drop an uninitialized `T`. I think `ptr::write` is infallible (can't panic), so it shouldn't matter. But *maybe* in debug mode it can panic if some invariant is broken (e.g. pointer not aligned). So play it safe and write the value first and update the cursor after. --- crates/oxc_transformer/src/helpers/stack/non_empty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/oxc_transformer/src/helpers/stack/non_empty.rs b/crates/oxc_transformer/src/helpers/stack/non_empty.rs index ecbb4a4a2..ef7403ae9 100644 --- a/crates/oxc_transformer/src/helpers/stack/non_empty.rs +++ b/crates/oxc_transformer/src/helpers/stack/non_empty.rs @@ -206,12 +206,12 @@ impl NonEmptyStack { unsafe { self.push_slow(value) }; } else { // Capacity for at least 1 more entry - self.cursor = new_cursor; // SAFETY: We checked there is capacity for 1 more entry, so `self.cursor` is in bounds. // `self.cursor` was aligned for `T`, and we added `size_of::()` to pointer. // `size_of::()` is always a multiple of `T`'s alignment, so `self.cursor` must still be // aligned for `T`. - unsafe { self.cursor.as_ptr().write(value) }; + unsafe { new_cursor.as_ptr().write(value) }; + self.cursor = new_cursor; } }