summaryrefslogtreecommitdiff
path: root/ops/lib.rs
diff options
context:
space:
mode:
authorAndreu Botella <andreu@andreubotella.com>2023-01-14 23:40:01 -0800
committerGitHub <noreply@github.com>2023-01-15 07:40:01 +0000
commit90c03812720c328dcb68939400b265128b6eca8f (patch)
treea1e5ce445e3c9d6eac7be43f1909cb354fe1e69d /ops/lib.rs
parent44d9acca75b5a0aa886bf370cd4658bfb6e7097e (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.rs10
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;