diff options
author | Andreu Botella <andreu@andreubotella.com> | 2023-01-14 23:40:01 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-15 07:40:01 +0000 |
commit | 90c03812720c328dcb68939400b265128b6eca8f (patch) | |
tree | a1e5ce445e3c9d6eac7be43f1909cb354fe1e69d /ops/lib.rs | |
parent | 44d9acca75b5a0aa886bf370cd4658bfb6e7097e (diff) |
fix(ops): disallow memory slices as inputs to async ops (#16738)
In Rust, it is UB if a slice is mutated while borrowed except through
the slice itself, and it is also UB if a mutable slice is read while
borrowed. The op macro allows borrowing an `ArrayBuffer{,View}` as a
memory slice for the duration of an op, but this is not sound for async
ops, since the `ArrayBuffer` could be accessed from JS during the await
points. This PR therefore disallows such automatic borrowing only for
async ops.
Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
Diffstat (limited to 'ops/lib.rs')
-rw-r--r-- | ops/lib.rs | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/ops/lib.rs b/ops/lib.rs index 5b215ed70..35796d41a 100644 --- a/ops/lib.rs +++ b/ops/lib.rs @@ -209,7 +209,7 @@ fn codegen_v8_async( let rust_i0 = special_args.len(); let args_head = special_args.into_iter().collect::<TokenStream2>(); - let (arg_decls, args_tail, argc) = codegen_args(core, f, rust_i0, 1); + let (arg_decls, args_tail, argc) = codegen_args(core, f, rust_i0, 1, true); let type_params = exclude_lifetime_params(&f.sig.generics.params); let (pre_result, mut result_fut) = match asyncness { @@ -330,7 +330,7 @@ fn codegen_v8_sync( .collect::<Vec<_>>(); let rust_i0 = special_args.len(); let args_head = special_args.into_iter().collect::<TokenStream2>(); - let (arg_decls, args_tail, argc) = codegen_args(core, f, rust_i0, 0); + let (arg_decls, args_tail, argc) = codegen_args(core, f, rust_i0, 0, false); let ret = codegen_sync_ret(core, &f.sig.output); let type_params = exclude_lifetime_params(&f.sig.generics.params); @@ -380,6 +380,7 @@ fn codegen_args( f: &syn::ItemFn, rust_i0: usize, // Index of first generic arg in rust v8_i0: usize, // Index of first generic arg in v8/js + asyncness: bool, ) -> ArgumentDecl { let inputs = &f.sig.inputs.iter().skip(rust_i0).enumerate(); let ident_seq: TokenStream2 = inputs @@ -392,7 +393,7 @@ fn codegen_args( let decls: TokenStream2 = inputs .clone() .map(|(i, arg)| { - codegen_arg(core, arg, format!("arg_{i}").as_ref(), v8_i0 + i) + codegen_arg(core, arg, format!("arg_{i}").as_ref(), v8_i0 + i, asyncness) }) .collect(); (decls, ident_seq, inputs.len()) @@ -403,6 +404,7 @@ fn codegen_arg( arg: &syn::FnArg, name: &str, idx: usize, + asyncness: bool, ) -> TokenStream2 { let ident = quote::format_ident!("{name}"); let (pat, ty) = match arg { @@ -444,12 +446,14 @@ fn codegen_arg( match is_ref_slice(&**ty) { None => {} Some(SliceType::U32Mut) => { + assert!(!asyncness, "Memory slices are not allowed in async ops"); let blck = codegen_u32_mut_slice(core, idx); return quote! { let #ident = #blck; }; } Some(_) => { + assert!(!asyncness, "Memory slices are not allowed in async ops"); let blck = codegen_u8_slice(core, idx); return quote! { let #ident = #blck; |