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/cache
~/.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
- name: Cache build output (main)
@ -252,7 +252,7 @@ jobs:
!./target/*/*.zip
!./target/*/*.tar.gz
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.
- name: Cache build output (PR)
@ -268,7 +268,7 @@ jobs:
!./target/*/*.tar.gz
key: never_saved
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'.
- name: Skip save cache (PR)

View file

@ -2523,3 +2523,93 @@ itest!(fetch_async_error_stack {
output: "fetch_async_error_stack.ts.out",
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);
}, 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 {
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_call::decl(),
op_ffi_call_nonblocking::decl(),
op_ffi_call_ptr::decl(),
op_ffi_call_ptr_nonblocking::decl(),
op_ffi_call_ptr::decl::<P>(),
op_ffi_call_ptr_nonblocking::decl::<P>(),
op_ffi_ptr_of::decl::<P>(),
op_ffi_buf_copy_into::decl::<P>(),
op_ffi_cstr_read::decl::<P>(),
@ -648,15 +653,38 @@ fn ffi_call(args: FfiCallArgs, symbol: &Symbol) -> Result<Value, AnyError> {
}
#[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();
ffi_call(args.into(), &symbol)
}
#[op]
async fn op_ffi_call_ptr_nonblocking(
async fn op_ffi_call_ptr_nonblocking<FP>(
state: Rc<RefCell<deno_core::OpState>>,
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();
tokio::task::spawn_blocking(move || ffi_call(args.into(), &symbol))
.await
@ -774,6 +802,8 @@ fn op_ffi_ptr_of<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointer#of");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -788,6 +818,8 @@ fn op_ffi_buf_copy_into<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#copyInto");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -810,6 +842,8 @@ fn op_ffi_cstr_read<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getCString");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -825,6 +859,8 @@ fn op_ffi_read_u8<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getUint8");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -839,6 +875,8 @@ fn op_ffi_read_i8<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getInt8");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -853,6 +891,8 @@ fn op_ffi_read_u16<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getUint16");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -867,6 +907,8 @@ fn op_ffi_read_i16<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getInt16");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -881,6 +923,8 @@ fn op_ffi_read_u32<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getUint32");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -895,6 +939,8 @@ fn op_ffi_read_i32<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getInt32");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -909,6 +955,8 @@ fn op_ffi_read_u64<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getBigUint64");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -925,6 +973,8 @@ fn op_ffi_read_f32<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getFloat32");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
@ -939,6 +989,8 @@ fn op_ffi_read_f64<FP>(
where
FP: FfiPermissions + 'static,
{
check_unstable(state, "Deno.UnsafePointerView#getFloat64");
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;