From 6c6149a847a8d80f943fec9f991c24ffd9d9ccb5 Mon Sep 17 00:00:00 2001 From: Jacob Kiesel Date: Fri, 7 Oct 2022 16:19:18 -0600 Subject: [PATCH] Fixes #1338 use after free with async --- crates/backend/src/codegen/fn.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/crates/backend/src/codegen/fn.rs b/crates/backend/src/codegen/fn.rs index 43d7e274e0..391a4f6984 100644 --- a/crates/backend/src/codegen/fn.rs +++ b/crates/backend/src/codegen/fn.rs @@ -35,19 +35,30 @@ impl TryToTokens for NapiFn { quote! { Ok(#receiver(#(#arg_names),*).await) } }; quote! { - napi::bindgen_prelude::execute_tokio_future(env, async move { #call }, |env, #receiver_ret_name| { + struct NapiRefContainer([napi::bindgen_prelude::sys::napi_ref; #args_len + 1]); + impl NapiRefContainer { + fn drop(self, env: napi::bindgen_prelude::sys::napi_env) { + for r in self.0 { + assert_eq!(unsafe { napi::bindgen_prelude::sys::napi_delete_reference(env, r) }, napi::bindgen_prelude::sys::Status::napi_ok); + } + } + } + unsafe impl Send for NapiRefContainer {} + unsafe impl Sync for NapiRefContainer {} + let mut arg_iter = cb.args.iter().chain(Some(&cb.this)).map(|a| { + let mut node_ref = ::std::mem::MaybeUninit::uninit(); + assert_eq!(unsafe { napi::bindgen_prelude::sys::napi_create_reference(env, *a, 1, node_ref.as_mut_ptr()) }, napi::bindgen_prelude::sys::Status::napi_ok); + unsafe { node_ref.assume_init() } + }); + let args_ref = NapiRefContainer(::std::array::from_fn(|_| arg_iter.next().expect("infallible"))); + napi::bindgen_prelude::execute_tokio_future(env, async move { #call }, move |env, #receiver_ret_name| { + args_ref.drop(env); #ret }) } }; - let function_call = if args_len == 0 - && self.fn_self.is_none() - && self.kind != FnKind::Constructor - && self.kind != FnKind::Factory - { - quote! { #native_call } - } else if self.kind == FnKind::Constructor { + let function_call = if self.kind == FnKind::Constructor { quote! { // constructor function is called from class `factory` // so we should skip the original `constructor` logic