1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

fix(ext/ffi): enforce unstable check on ops (#14115)

This commit is contained in:
Luca Casonato 2022-03-25 12:29:54 +01:00
parent 3953059b74
commit fcfce1bb86
No known key found for this signature in database
GPG key ID: 01A83EB62563811F
34 changed files with 249 additions and 8 deletions

View file

@ -236,7 +236,7 @@ jobs:
~/.cargo/registry/index ~/.cargo/registry/index
~/.cargo/registry/cache ~/.cargo/registry/cache
~/.cargo/git/db ~/.cargo/git/db
key: 4-cargo-home-${{ matrix.os }}-${{ hashFiles('Cargo.lock') }} key: 5-cargo-home-${{ matrix.os }}-${{ hashFiles('Cargo.lock') }}
# In main branch, always creates fresh cache # In main branch, always creates fresh cache
- name: Cache build output (main) - name: Cache build output (main)
@ -252,7 +252,7 @@ jobs:
!./target/*/*.zip !./target/*/*.zip
!./target/*/*.tar.gz !./target/*/*.tar.gz
key: | key: |
4-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ github.sha }} 5-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ github.sha }}
# Restore cache from the latest 'main' branch build. # Restore cache from the latest 'main' branch build.
- name: Cache build output (PR) - name: Cache build output (PR)
@ -268,7 +268,7 @@ jobs:
!./target/*/*.tar.gz !./target/*/*.tar.gz
key: never_saved key: never_saved
restore-keys: | restore-keys: |
4-cargo-target-${{ matrix.os }}-${{ matrix.profile }}- 5-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-
# Don't save cache after building PRs or branches other than 'main'. # Don't save cache after building PRs or branches other than 'main'.
- name: Skip save cache (PR) - name: Skip save cache (PR)

View file

@ -2523,3 +2523,93 @@ itest!(fetch_async_error_stack {
output: "fetch_async_error_stack.ts.out", output: "fetch_async_error_stack.ts.out",
exit_code: 1, exit_code: 1,
}); });
itest!(unstable_ffi_1 {
args: "run unstable_ffi_1.js",
output: "unstable_ffi_1.js.out",
exit_code: 70,
});
itest!(unstable_ffi_2 {
args: "run unstable_ffi_2.js",
output: "unstable_ffi_2.js.out",
exit_code: 70,
});
itest!(unstable_ffi_3 {
args: "run unstable_ffi_3.js",
output: "unstable_ffi_3.js.out",
exit_code: 70,
});
itest!(unstable_ffi_4 {
args: "run unstable_ffi_4.js",
output: "unstable_ffi_4.js.out",
exit_code: 70,
});
itest!(unstable_ffi_5 {
args: "run unstable_ffi_5.js",
output: "unstable_ffi_5.js.out",
exit_code: 70,
});
itest!(unstable_ffi_6 {
args: "run unstable_ffi_6.js",
output: "unstable_ffi_6.js.out",
exit_code: 70,
});
itest!(unstable_ffi_7 {
args: "run unstable_ffi_7.js",
output: "unstable_ffi_7.js.out",
exit_code: 70,
});
itest!(unstable_ffi_8 {
args: "run unstable_ffi_8.js",
output: "unstable_ffi_8.js.out",
exit_code: 70,
});
itest!(unstable_ffi_9 {
args: "run unstable_ffi_9.js",
output: "unstable_ffi_9.js.out",
exit_code: 70,
});
itest!(unstable_ffi_10 {
args: "run unstable_ffi_10.js",
output: "unstable_ffi_10.js.out",
exit_code: 70,
});
itest!(unstable_ffi_11 {
args: "run unstable_ffi_11.js",
output: "unstable_ffi_11.js.out",
exit_code: 70,
});
itest!(unstable_ffi_12 {
args: "run unstable_ffi_12.js",
output: "unstable_ffi_12.js.out",
exit_code: 70,
});
itest!(unstable_ffi_13 {
args: "run unstable_ffi_13.js",
output: "unstable_ffi_13.js.out",
exit_code: 70,
});
itest!(unstable_ffi_14 {
args: "run unstable_ffi_14.js",
output: "unstable_ffi_14.js.out",
exit_code: 70,
});
itest!(unstable_ffi_15 {
args: "run unstable_ffi_15.js",
output: "unstable_ffi_15.js.out",
exit_code: 70,
});

1
cli/tests/testdata/unstable_ffi_1.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_load", { path: "", symbols: {} });

View file

@ -0,0 +1 @@
Unstable API 'Deno.dlopen'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_10.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_i16", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getInt16'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_11.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_u32", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getUint32'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_12.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_i32", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getInt32'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_13.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_u64", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getBigUint64'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_14.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_f32", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getFloat32'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_15.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_f64", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getFloat64'. The --unstable flag must be provided.

10
cli/tests/testdata/unstable_ffi_2.js vendored Normal file
View file

@ -0,0 +1,10 @@
Deno.core.opSync("op_ffi_call_ptr", {
pointer: [0, 0],
def: {
name: null,
parameters: [],
result: "void",
},
parameters: [],
buffers: [],
});

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafeFnPointer#call'. The --unstable flag must be provided.

10
cli/tests/testdata/unstable_ffi_3.js vendored Normal file
View file

@ -0,0 +1,10 @@
Deno.core.opAsync("op_ffi_call_ptr_nonblocking", {
pointer: [0, 0],
def: {
name: null,
parameters: [],
result: "void",
},
parameters: [],
buffers: [],
});

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafeFnPointer#call'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_4.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_ptr_of", new Uint8Array(0));

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointer#of'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_5.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_buf_copy_into", [[0, 0], new Uint8Array(0), 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#copyInto'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_6.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_cstr_read", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getCString'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_7.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_u8", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getUint8'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_8.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_i8", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getInt8'. The --unstable flag must be provided.

1
cli/tests/testdata/unstable_ffi_9.js vendored Normal file
View file

@ -0,0 +1 @@
Deno.core.opSync("op_ffi_read_u16", [0, 0]);

View file

@ -0,0 +1 @@
Unstable API 'Deno.UnsafePointerView#getUint16'. The --unstable flag must be provided.

View file

@ -23,3 +23,54 @@ Deno.test({ permissions: { ffi: true } }, function dlopenInvalidArguments() {
Deno.dlopen(filename); Deno.dlopen(filename);
}, TypeError); }, TypeError);
}); });
Deno.test({ permissions: { ffi: false } }, function ffiPermissionDenied() {
assertThrows(() => {
Deno.dlopen("/usr/lib/libc.so.6", {});
}, Deno.errors.PermissionDenied);
const ptr = new Deno.UnsafePointer(0n);
const fnptr = new Deno.UnsafeFnPointer(
ptr,
{
parameters: ["u32", "pointer"],
result: "void",
} as const,
);
assertThrows(() => {
fnptr.call(123, null);
}, Deno.errors.PermissionDenied);
assertThrows(() => {
Deno.UnsafePointer.of(new Uint8Array(0));
}, Deno.errors.PermissionDenied);
const ptrView = new Deno.UnsafePointerView(ptr);
assertThrows(() => {
ptrView.copyInto(new Uint8Array(0));
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getCString();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getUint8();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getInt8();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getUint16();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getInt16();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getUint32();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getInt32();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getFloat32();
}, Deno.errors.PermissionDenied);
assertThrows(() => {
ptrView.getFloat64();
}, Deno.errors.PermissionDenied);
});

View file

@ -45,6 +45,11 @@ fn check_unstable(state: &OpState, api_name: &str) {
} }
} }
pub fn check_unstable2(state: &Rc<RefCell<OpState>>, api_name: &str) {
let state = state.borrow();
check_unstable(&state, api_name)
}
pub trait FfiPermissions { pub trait FfiPermissions {
fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError>; fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError>;
} }
@ -144,8 +149,8 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
op_ffi_get_static::decl(), op_ffi_get_static::decl(),
op_ffi_call::decl(), op_ffi_call::decl(),
op_ffi_call_nonblocking::decl(), op_ffi_call_nonblocking::decl(),
op_ffi_call_ptr::decl(), op_ffi_call_ptr::decl::<P>(),
op_ffi_call_ptr_nonblocking::decl(), op_ffi_call_ptr_nonblocking::decl::<P>(),
op_ffi_ptr_of::decl::<P>(), op_ffi_ptr_of::decl::<P>(),
op_ffi_buf_copy_into::decl::<P>(), op_ffi_buf_copy_into::decl::<P>(),
op_ffi_cstr_read::decl::<P>(), op_ffi_cstr_read::decl::<P>(),
@ -648,15 +653,38 @@ fn ffi_call(args: FfiCallArgs, symbol: &Symbol) -> Result<Value, AnyError> {
} }
#[op] #[op]
fn op_ffi_call_ptr(args: FfiCallPtrArgs) -> Result<Value, AnyError> { fn op_ffi_call_ptr<FP>(
state: &mut deno_core::OpState,
args: FfiCallPtrArgs,
) -> Result<Value, AnyError>
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafeFnPointer#call");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
let symbol = args.get_symbol(); let symbol = args.get_symbol();
ffi_call(args.into(), &symbol) ffi_call(args.into(), &symbol)
} }
#[op] #[op]
async fn op_ffi_call_ptr_nonblocking( async fn op_ffi_call_ptr_nonblocking<FP>(
state: Rc<RefCell<deno_core::OpState>>,
args: FfiCallPtrArgs, args: FfiCallPtrArgs,
) -> Result<Value, AnyError> { ) -> Result<Value, AnyError>
where
FP: FfiPermissions + 'static,
{
check_unstable2(&state, "Deno.UnsafeFnPointer#call");
{
let mut state = state.borrow_mut();
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
}
let symbol = args.get_symbol(); let symbol = args.get_symbol();
tokio::task::spawn_blocking(move || ffi_call(args.into(), &symbol)) tokio::task::spawn_blocking(move || ffi_call(args.into(), &symbol))
.await .await
@ -774,6 +802,8 @@ fn op_ffi_ptr_of<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointer#of");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -788,6 +818,8 @@ fn op_ffi_buf_copy_into<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#copyInto");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -810,6 +842,8 @@ fn op_ffi_cstr_read<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getCString");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -825,6 +859,8 @@ fn op_ffi_read_u8<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getUint8");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -839,6 +875,8 @@ fn op_ffi_read_i8<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getInt8");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -853,6 +891,8 @@ fn op_ffi_read_u16<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getUint16");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -867,6 +907,8 @@ fn op_ffi_read_i16<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getInt16");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -881,6 +923,8 @@ fn op_ffi_read_u32<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getUint32");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -895,6 +939,8 @@ fn op_ffi_read_i32<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getInt32");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -909,6 +955,8 @@ fn op_ffi_read_u64<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getBigUint64");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -925,6 +973,8 @@ fn op_ffi_read_f32<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getFloat32");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;
@ -939,6 +989,8 @@ fn op_ffi_read_f64<FP>(
where where
FP: FfiPermissions + 'static, FP: FfiPermissions + 'static,
{ {
check_unstable(state, "Deno.UnsafePointerView#getFloat64");
let permissions = state.borrow_mut::<FP>(); let permissions = state.borrow_mut::<FP>();
permissions.check(None)?; permissions.check(None)?;