summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2022-06-26 00:13:24 +0200
committerGitHub <noreply@github.com>2022-06-26 00:13:24 +0200
commit8d82ba729937baf83011354242cabc3d50c13dc2 (patch)
tree3e8c4d87986338639eeef4a76543e4335020262c
parent38505db39137f33bfdb942658ea892a617ac0980 (diff)
build: require safety comments on unsafe code (#13870)
Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com> Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
-rw-r--r--cli/bench/http.rs10
-rw-r--r--cli/deno_dir.rs8
-rw-r--r--cli/lsp/logging.rs6
-rw-r--r--cli/lsp/parent_process_checker.rs2
-rw-r--r--cli/unix_util.rs2
-rw-r--r--core/async_cancel.rs25
-rw-r--r--core/async_cell.rs34
-rw-r--r--core/bindings.rs4
-rw-r--r--core/inspector.rs13
-rw-r--r--core/modules.rs1
-rw-r--r--core/ops.rs2
-rw-r--r--core/ops_metrics.rs5
-rw-r--r--core/resources.rs2
-rw-r--r--core/runtime.rs5
-rw-r--r--ext/ffi/lib.rs128
-rw-r--r--ext/net/ops_tls.rs20
-rw-r--r--ext/webgpu/src/buffer.rs6
-rw-r--r--runtime/ops/io.rs33
-rw-r--r--runtime/ops/os.rs12
-rw-r--r--runtime/ops/process.rs2
-rw-r--r--runtime/ops/spawn.rs2
-rw-r--r--runtime/ops/tty.rs6
-rw-r--r--runtime/permissions.rs2
-rw-r--r--serde_v8/examples/basic.rs2
-rw-r--r--serde_v8/magic/rawbytes.rs2
-rw-r--r--serde_v8/serializable.rs2
-rw-r--r--serde_v8/utils.rs1
-rw-r--r--test_ffi/src/lib.rs40
-rwxr-xr-xtools/lint.js4
29 files changed, 294 insertions, 87 deletions
diff --git a/cli/bench/http.rs b/cli/bench/http.rs
index 83f8eef8b..770642907 100644
--- a/cli/bench/http.rs
+++ b/cli/bench/http.rs
@@ -153,11 +153,13 @@ fn run(
fn get_port() -> u16 {
static mut NEXT_PORT: u16 = 4544;
- let port = unsafe { NEXT_PORT };
-
- unsafe {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ let port = unsafe {
+ let p = NEXT_PORT;
NEXT_PORT += 1;
- }
+ p
+ };
port
}
diff --git a/cli/deno_dir.rs b/cli/deno_dir.rs
index ea46474d0..c6a5eca29 100644
--- a/cli/deno_dir.rs
+++ b/cli/deno_dir.rs
@@ -76,7 +76,13 @@ mod dirs {
pub fn home_dir() -> Option<PathBuf> {
std::env::var_os("HOME")
.and_then(|h| if h.is_empty() { None } else { Some(h) })
- .or_else(|| unsafe { fallback() })
+ .or_else(|| {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ fallback()
+ }
+ })
.map(PathBuf::from)
}
diff --git a/cli/lsp/logging.rs b/cli/lsp/logging.rs
index b3fc06d89..88392dca2 100644
--- a/cli/lsp/logging.rs
+++ b/cli/lsp/logging.rs
@@ -21,7 +21,11 @@ pub fn set_lsp_log_level(level: log::Level) {
pub fn lsp_log_level() -> log::Level {
let level = LSP_LOG_LEVEL.load(Ordering::SeqCst);
- unsafe { std::mem::transmute(level) }
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ std::mem::transmute(level)
+ }
}
/// Use this macro to do "info" logs in the lsp code. This allows
diff --git a/cli/lsp/parent_process_checker.rs b/cli/lsp/parent_process_checker.rs
index f4bf99d3e..e4a359bd9 100644
--- a/cli/lsp/parent_process_checker.rs
+++ b/cli/lsp/parent_process_checker.rs
@@ -20,6 +20,8 @@ pub fn start(parent_process_id: u32) {
#[cfg(unix)]
fn is_process_active(process_id: u32) -> bool {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
// signal of 0 checks for the existence of the process id
libc::kill(process_id as i32, 0) == 0
diff --git a/cli/unix_util.rs b/cli/unix_util.rs
index 927b99d64..f282f6cfe 100644
--- a/cli/unix_util.rs
+++ b/cli/unix_util.rs
@@ -4,6 +4,8 @@
/// This is the difference between `ulimit -n` and `ulimit -n -H`.
pub fn raise_fd_limit() {
#[cfg(unix)]
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
let mut limits = libc::rlimit {
rlim_cur: 0,
diff --git a/core/async_cancel.rs b/core/async_cancel.rs
index cf338174d..55ab8f4d1 100644
--- a/core/async_cancel.rs
+++ b/core/async_cancel.rs
@@ -302,13 +302,19 @@ mod internal {
Some((head, rc)) => {
// Register this `Cancelable` node with a `CancelHandle` head node.
assert_ne!(self, head);
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let self_inner = unsafe { &mut *self.inner.get() };
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let head_inner = unsafe { &mut *head.inner.get() };
self_inner.link(waker, head_inner, rc)
}
None => {
// This `Cancelable` has already been linked to a `CancelHandle` head
// node; just update our stored `Waker` if necessary.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.update_waker(waker)
}
@@ -316,11 +322,15 @@ mod internal {
}
pub fn cancel(&self) {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.cancel();
}
pub fn is_canceled(&self) -> bool {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.is_canceled()
}
@@ -337,6 +347,8 @@ mod internal {
impl Drop for Node {
fn drop(&mut self) {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.unlink();
}
@@ -392,6 +404,8 @@ mod internal {
prev: next_prev_nn,
..
} => {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let prev = unsafe { &mut *next_prev_nn.as_ptr() };
match prev {
NodeInner::Linked {
@@ -444,10 +458,14 @@ mod internal {
if prev_nn == next_nn {
// There were only two nodes in this chain; after unlinking ourselves
// the other node is no longer linked.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let other = unsafe { prev_nn.as_mut() };
*other = NodeInner::Unlinked;
} else {
// The chain had more than two nodes.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
match unsafe { prev_nn.as_mut() } {
NodeInner::Linked {
next: prev_next_nn, ..
@@ -456,6 +474,8 @@ mod internal {
}
_ => unreachable!(),
}
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
match unsafe { next_nn.as_mut() } {
NodeInner::Linked {
prev: next_prev_nn, ..
@@ -473,6 +493,8 @@ mod internal {
fn cancel(&mut self) {
let mut head_nn = NonNull::from(self);
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
// Mark the head node as canceled.
let mut item_nn =
match replace(unsafe { head_nn.as_mut() }, NodeInner::Canceled) {
@@ -487,6 +509,8 @@ mod internal {
// Cancel all item nodes in the chain, waking each stored `Waker`.
while item_nn != head_nn {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
match replace(unsafe { item_nn.as_mut() }, NodeInner::Canceled) {
NodeInner::Linked {
kind: NodeKind::Item { waker },
@@ -745,6 +769,7 @@ mod tests {
assert!(Rc::get_mut(&mut cancel_handle).is_some());
let mut future = pending::<Never>().or_cancel(&cancel_handle);
+ // SAFETY: `Cancelable` pins the future
let future = unsafe { Pin::new_unchecked(&mut future) };
// There are two `Rc<CancelHandle>` references now, so this fails.
diff --git a/core/async_cell.rs b/core/async_cell.rs
index 8798861cf..ea6cac831 100644
--- a/core/async_cell.rs
+++ b/core/async_cell.rs
@@ -157,12 +157,16 @@ impl<T: 'static> RcRef<T> {
map_fn: F,
) -> RcRef<T> {
let RcRef::<S> { rc, value } = source.into();
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let value = map_fn(unsafe { &*value });
RcRef { rc, value }
}
pub(crate) fn split(rc_ref: &Self) -> (&T, &Rc<dyn Any>) {
let &Self { ref rc, value } = rc_ref;
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
(unsafe { &*value }, rc)
}
}
@@ -206,7 +210,11 @@ impl<T: 'static> From<&Rc<T>> for RcRef<T> {
impl<T> Deref for RcRef<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
- unsafe { &*self.value }
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &*self.value
+ }
}
}
@@ -260,6 +268,8 @@ mod internal {
// Don't allow synchronous borrows to cut in line; if there are any
// enqueued waiters, return `None`, even if the current borrow is a shared
// one and the requested borrow is too.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *cell_ref.waiters.as_ptr() };
if waiters.is_empty() {
// There are no enqueued waiters, but it is still possible that the cell
@@ -288,6 +298,8 @@ mod internal {
let waiter = Waiter::new(M::borrow_mode());
let turn = self.turn.get();
let index = {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
waiters.push_back(Some(waiter));
waiters.len() - 1
@@ -315,6 +327,8 @@ mod internal {
Poll::Ready(())
} else {
// This waiter is still in line and has not yet been woken.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
// Sanity check: id cannot be higher than the last queue element.
assert!(id < turn + waiters.len());
@@ -330,6 +344,8 @@ mod internal {
fn wake_waiters(&self) {
let mut borrow_count = self.borrow_count.get();
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
let mut turn = self.turn.get();
@@ -379,6 +395,8 @@ mod internal {
self.drop_borrow::<M>();
} else {
// This waiter is still in the queue, take it out and leave a "hole".
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
waiters[id - turn].take().unwrap();
}
@@ -411,6 +429,8 @@ mod internal {
type Output = AsyncBorrowImpl<T, M>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
ready!(self.cell.as_ref().unwrap().poll_waiter::<M>(self.id, cx));
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let self_mut = unsafe { Pin::get_unchecked_mut(self) };
let cell = self_mut.cell.take().unwrap();
Poll::Ready(AsyncBorrowImpl::<T, M>::new(cell))
@@ -448,7 +468,11 @@ mod internal {
impl<T, M: BorrowModeTrait> Deref for AsyncBorrowImpl<T, M> {
type Target = T;
fn deref(&self) -> &Self::Target {
- unsafe { &*self.cell.as_ptr() }
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &*self.cell.as_ptr()
+ }
}
}
@@ -466,7 +490,11 @@ mod internal {
impl<T> DerefMut for AsyncBorrowImpl<T, Exclusive> {
fn deref_mut(&mut self) -> &mut Self::Target {
- unsafe { &mut *self.cell.as_ptr() }
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &mut *self.cell.as_ptr()
+ }
}
}
diff --git a/core/bindings.rs b/core/bindings.rs
index 5681ded31..a88e54af7 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -147,6 +147,7 @@ pub extern "C" fn host_import_module_dynamically_callback(
specifier: v8::Local<v8::String>,
import_assertions: v8::Local<v8::FixedArray>,
) -> *mut v8::Promise {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
// NOTE(bartlomieju): will crash for non-UTF-8 specifier
@@ -253,6 +254,7 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
module: v8::Local<v8::Module>,
meta: v8::Local<v8::Object>,
) {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
let module_map_rc = JsRuntime::module_map(scope);
let module_map = module_map_rc.borrow();
@@ -274,6 +276,7 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) {
use v8::PromiseRejectEvent::*;
+ // SAFETY: `CallbackScope` can be safely constructed from `&PromiseRejectMessage`
let scope = &mut unsafe { v8::CallbackScope::new(&message) };
let state_rc = JsRuntime::state(scope);
@@ -418,6 +421,7 @@ pub fn module_resolve_callback<'s>(
import_assertions: v8::Local<'s, v8::FixedArray>,
referrer: v8::Local<'s, v8::Module>,
) -> Option<v8::Local<'s, v8::Module>> {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
let module_map_rc = JsRuntime::module_map(scope);
diff --git a/core/inspector.rs b/core/inspector.rs
index 26855acdf..bec22d257 100644
--- a/core/inspector.rs
+++ b/core/inspector.rs
@@ -485,6 +485,8 @@ impl task::ArcWake for InspectorWaker {
_isolate: &mut v8::Isolate,
arg: *mut c_void,
) {
+ // SAFETY: `InspectorWaker` is owned by `JsRuntimeInspector`, so the
+ // pointer to the latter is valid as long as waker is alive.
let inspector = unsafe { &*(arg as *mut JsRuntimeInspector) };
let _ = inspector.poll_sessions(None);
}
@@ -521,6 +523,8 @@ impl InspectorSession {
let v8_channel = v8::inspector::ChannelBase::new::<Self>();
let mut v8_inspector = v8_inspector_rc.borrow_mut();
let v8_inspector_ptr = v8_inspector.as_mut().unwrap();
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let v8_session = v8_inspector_ptr.connect(
Self::CONTEXT_GROUP_ID,
// Todo(piscisaureus): V8Inspector::connect() should require that
@@ -544,6 +548,8 @@ impl InspectorSession {
msg: String,
) {
let msg = v8::inspector::StringView::from(msg.as_bytes());
+ // SAFETY: `InspectorSession` is the only owner of `v8_session_ptr`, so
+ // the pointer is valid for as long the struct.
unsafe {
(*v8_session_ptr).dispatch_protocol_message(msg);
};
@@ -731,6 +737,9 @@ impl LocalInspectorSession {
fn new_box_with<T>(new_fn: impl FnOnce(*mut T) -> T) -> Box<T> {
let b = Box::new(MaybeUninit::<T>::uninit());
let p = Box::into_raw(b) as *mut T;
- unsafe { ptr::write(p, new_fn(p)) };
- unsafe { Box::from_raw(p) }
+ // SAFETY: memory layout for `T` is ensured on first line of this function
+ unsafe {
+ ptr::write(p, new_fn(p));
+ Box::from_raw(p)
+ }
}
diff --git a/core/modules.rs b/core/modules.rs
index e86fdbf73..aec8c498f 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -122,6 +122,7 @@ fn json_module_evaluation_steps<'a>(
context: v8::Local<'a, v8::Context>,
module: v8::Local<v8::Module>,
) -> Option<v8::Local<'a, v8::Value>> {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
let tc_scope = &mut v8::TryCatch::new(scope);
let module_map = tc_scope
diff --git a/core/ops.rs b/core/ops.rs
index a2833e811..3d0d0ec70 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -63,6 +63,8 @@ impl<T> Future for OpCall<T> {
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut self.get_unchecked_mut().0 };
let mut pinned = Pin::new(inner);
ready!(pinned.as_mut().poll(cx));
diff --git a/core/ops_metrics.rs b/core/ops_metrics.rs
index b068aa0ee..aa3ff503b 100644
--- a/core/ops_metrics.rs
+++ b/core/ops_metrics.rs
@@ -56,12 +56,17 @@ impl OpsTracker {
#[allow(clippy::mut_from_ref)]
#[inline]
fn ops_mut(&self) -> &mut Vec<OpMetrics> {
+ // SAFETY: `OpsTracker` is created after registering ops so it is guaranteed
+ // that that `ops` will be initialized.
unsafe { &mut *self.ops.get() }
}
#[allow(clippy::mut_from_ref)]
#[inline]
fn metrics_mut(&self, id: OpId) -> &mut OpMetrics {
+ // SAFETY: `OpsTracker` is created after registering ops, and ops
+ // cannot be unregistered during runtime, so it is guaranteed that `id`
+ // is not causing out-of-bound access.
unsafe { self.ops_mut().get_unchecked_mut(id) }
}
diff --git a/core/resources.rs b/core/resources.rs
index ae4ef7394..a4bb3607d 100644
--- a/core/resources.rs
+++ b/core/resources.rs
@@ -77,6 +77,8 @@ impl dyn Resource {
pub fn downcast_rc<'a, T: Resource>(self: &'a Rc<Self>) -> Option<&'a Rc<T>> {
if self.is::<T>() {
let ptr = self as *const Rc<_> as *const Rc<T>;
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
Some(unsafe { &*ptr })
} else {
None
diff --git a/core/runtime.rs b/core/runtime.rs
index f82f06207..7cb556fd3 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -333,6 +333,9 @@ impl JsRuntime {
assert!(options.startup_snapshot.is_none());
let mut creator =
v8::SnapshotCreator::new(Some(&bindings::EXTERNAL_REFERENCES));
+ // SAFETY: `get_owned_isolate` is unsafe because it may only be called
+ // once. This is the only place we call this function, so this call is
+ // safe.
let isolate = unsafe { creator.get_owned_isolate() };
let mut isolate = JsRuntime::setup_isolate(isolate);
{
@@ -1028,6 +1031,8 @@ extern "C" fn near_heap_limit_callback<F>(
where
F: FnMut(usize, usize) -> usize,
{
+ // SAFETY: The data is a pointer to the Rust callback function. It is stored
+ // in `JsRuntime::allocations` and thus is guaranteed to outlive the isolate.
let callback = unsafe { &mut *(data as *mut F) };
callback(current_heap_limit, initial_heap_limit)
}
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index 4c306e7f4..41b2f0a3b 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -130,6 +130,8 @@ impl DynamicLibraryResource {
// By default, Err returned by this function does not tell
// which symbol wasn't exported. So we'll modify the error
// message to include the name of symbol.
+ //
+ // SAFETY: The obtained T symbol is the size of a pointer.
let fn_ptr = match unsafe { self.lib.symbol::<*const c_void>(symbol) } {
Ok(value) => Ok(value),
Err(err) => Err(generic_error(format!(
@@ -164,6 +166,8 @@ impl DynamicLibraryResource {
// By default, Err returned by this function does not tell
// which symbol wasn't exported. So we'll modify the error
// message to include the name of symbol.
+ //
+ // SAFETY: The obtained T symbol is the size of a pointer.
match unsafe { self.lib.symbol::<*const c_void>(&symbol) } {
Ok(value) => Ok(Ok(value)),
Err(err) => Err(generic_error(format!(
@@ -743,55 +747,60 @@ fn ffi_call(
let call_args: Vec<Arg> = call_args
.iter()
.enumerate()
- .map(|(index, ffi_arg)| unsafe {
- ffi_arg.as_arg(*parameter_types.get(index).unwrap())
+ .map(|(index, ffi_arg)| {
+ // SAFETY: the union field is initialized
+ unsafe { ffi_arg.as_arg(*parameter_types.get(index).unwrap()) }
})
.collect();
- Ok(match result_type {
- NativeType::Void => NativeValue {
- void_value: unsafe { cif.call::<()>(fun_ptr, &call_args) },
- },
- NativeType::U8 => NativeValue {
- u8_value: unsafe { cif.call::<u8>(fun_ptr, &call_args) },
- },
- NativeType::I8 => NativeValue {
- i8_value: unsafe { cif.call::<i8>(fun_ptr, &call_args) },
- },
- NativeType::U16 => NativeValue {
- u16_value: unsafe { cif.call::<u16>(fun_ptr, &call_args) },
- },
- NativeType::I16 => NativeValue {
- i16_value: unsafe { cif.call::<i16>(fun_ptr, &call_args) },
- },
- NativeType::U32 => NativeValue {
- u32_value: unsafe { cif.call::<u32>(fun_ptr, &call_args) },
- },
- NativeType::I32 => NativeValue {
- i32_value: unsafe { cif.call::<i32>(fun_ptr, &call_args) },
- },
- NativeType::U64 => NativeValue {
- u64_value: unsafe { cif.call::<u64>(fun_ptr, &call_args) },
- },
- NativeType::I64 => NativeValue {
- i64_value: unsafe { cif.call::<i64>(fun_ptr, &call_args) },
- },
- NativeType::USize => NativeValue {
- usize_value: unsafe { cif.call::<usize>(fun_ptr, &call_args) },
- },
- NativeType::ISize => NativeValue {
- isize_value: unsafe { cif.call::<isize>(fun_ptr, &call_args) },
- },
- NativeType::F32 => NativeValue {
- f32_value: unsafe { cif.call::<f32>(fun_ptr, &call_args) },
- },
- NativeType::F64 => NativeValue {
- f64_value: unsafe { cif.call::<f64>(fun_ptr, &call_args) },
- },
- NativeType::Pointer | NativeType::Function => NativeValue {
- pointer: unsafe { cif.call::<*const u8>(fun_ptr, &call_args) },
- },
- })
+ // SAFETY: types in the `Cif` match the actual calling convention and
+ // types of symbol.
+ unsafe {
+ Ok(match result_type {
+ NativeType::Void => NativeValue {
+ void_value: cif.call::<()>(fun_ptr, &call_args),
+ },
+ NativeType::U8 => NativeValue {
+ u8_value: cif.call::<u8>(fun_ptr, &call_args),
+ },
+ NativeType::I8 => NativeValue {
+ i8_value: cif.call::<i8>(fun_ptr, &call_args),
+ },
+ NativeType::U16 => NativeValue {
+ u16_value: cif.call::<u16>(fun_ptr, &call_args),
+ },
+ NativeType::I16 => NativeValue {
+ i16_value: cif.call::<i16>(fun_ptr, &call_args),
+ },
+ NativeType::U32 => NativeValue {
+ u32_value: cif.call::<u32>(fun_ptr, &call_args),
+ },
+ NativeType::I32 => NativeValue {
+ i32_value: cif.call::<i32>(fun_ptr, &call_args),
+ },
+ NativeType::U64 => NativeValue {
+ u64_value: cif.call::<u64>(fun_ptr, &call_args),
+ },
+ NativeType::I64 => NativeValue {
+ i64_value: cif.call::<i64>(fun_ptr, &call_args),
+ },
+ NativeType::USize => NativeValue {
+ usize_value: cif.call::<usize>(fun_ptr, &call_args),
+ },
+ NativeType::ISize => NativeValue {
+ isize_value: cif.call::<isize>(fun_ptr, &call_args),
+ },
+ NativeType::F32 => NativeValue {
+ f32_value: cif.call::<f32>(fun_ptr, &call_args),
+ },
+ NativeType::F64 => NativeValue {
+ f64_value: cif.call::<f64>(fun_ptr, &call_args),
+ },
+ NativeType::Pointer | NativeType::Function => NativeValue {
+ pointer: cif.call::<*const u8>(fun_ptr, &call_args),
+ },
+ })
+ }
}
struct UnsafeCallbackResource {
@@ -1201,71 +1210,83 @@ fn op_ffi_get_static<'scope>(
return Err(type_error("Invalid FFI static type 'void'"));
}
NativeType::U8 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u8) };
let number: v8::Local<v8::Value> =
v8::Integer::new_from_unsigned(scope, result as u32).into();
number.into()
}
NativeType::I8 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i8) };
let number: v8::Local<v8::Value> =
v8::Integer::new(scope, result as i32).into();
number.into()
}
NativeType::U16 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u16) };
let number: v8::Local<v8::Value> =
v8::Integer::new_from_unsigned(scope, result as u32).into();
number.into()
}
NativeType::I16 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i16) };
let number: v8::Local<v8::Value> =
v8::Integer::new(scope, result as i32).into();
number.into()
}
NativeType::U32 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u32) };
let number: v8::Local<v8::Value> =
v8::Integer::new_from_unsigned(scope, result).into();
number.into()
}
NativeType::I32 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i32) };
let number: v8::Local<v8::Value> = v8::Integer::new(scope, result).into();
number.into()
}
NativeType::U64 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u64) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_u64(scope, result).into();
big_int.into()
}
NativeType::I64 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i64) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_i64(scope, result).into();
big_int.into()
}
NativeType::USize => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const usize) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_u64(scope, result as u64).into();
big_int.into()
}
NativeType::ISize => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const isize) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_i64(scope, result as i64).into();
big_int.into()
}
NativeType::F32 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const f32) };
let number: v8::Local<v8::Value> =
v8::Number::new(scope, result as f64).into();
number.into()
}
NativeType::F64 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const f64) };
let number: v8::Local<v8::Value> = v8::Number::new(scope, result).into();
number.into()
@@ -1339,7 +1360,7 @@ fn op_ffi_call_nonblocking<'scope>(
cif,
ptr,
parameter_types,
- ..
+ result_type,
} = symbol.clone();
ffi_call(call_args, &cif, ptr, &parameter_types, result_type)
});
@@ -1392,6 +1413,8 @@ where
))
} else {
let src = src as *const u8;
+ // SAFETY: src is user defined.
+ // dest is properly aligned and is valid for writes of len * size_of::<T>() bytes.
unsafe { ptr::copy(src, dst.as_mut_ptr(), len) };
Ok(())
}
@@ -1411,6 +1434,8 @@ where
permissions.check(None)?;
let ptr = ptr as *const c_char;
+ // SAFETY: ptr is user provided
+ // lifetime validity is not an issue because we allocate a new string.
Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string())
}
@@ -1427,6 +1452,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const u8) })
}
@@ -1443,6 +1469,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const i8) })
}
@@ -1459,6 +1486,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const u16) })
}
@@ -1475,6 +1503,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const i16) })
}
@@ -1491,6 +1520,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const u32) })
}
@@ -1507,6 +1537,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const i32) })
}
@@ -1525,6 +1556,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
let result = unsafe { ptr::read_unaligned(ptr as *const u64) };
let big_int: v8::Local<v8::Value> =
@@ -1545,6 +1577,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const f32) })
}
@@ -1561,6 +1594,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const f64) })
}
diff --git a/ext/net/ops_tls.rs b/ext/net/ops_tls.rs
index 8892ea0ac..1c91674df 100644
--- a/ext/net/ops_tls.rs
+++ b/ext/net/ops_tls.rs
@@ -375,11 +375,17 @@ impl TlsStreamInner {
ready!(self.poll_io(cx, Flow::Read))?;
if self.rd_state == State::StreamOpen {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let buf_slice =
unsafe { &mut *(buf.unfilled_mut() as *mut [_] as *mut [u8]) };
let bytes_read = self.tls.reader().read(buf_slice)?;
assert_ne!(bytes_read, 0);
- unsafe { buf.assume_init(bytes_read) };
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ buf.assume_init(bytes_read)
+ };
buf.advance(bytes_read);
}
@@ -581,10 +587,16 @@ impl Shared {
let self_weak = Arc::downgrade(self);
let self_ptr = self_weak.into_raw() as *const ();
let raw_waker = RawWaker::new(self_ptr, &Self::SHARED_WAKER_VTABLE);
- unsafe { Waker::from_raw(raw_waker) }
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ Waker::from_raw(raw_waker)
+ }
}
fn clone_shared_waker(self_ptr: *const ()) -> RawWaker {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let self_weak = unsafe { Weak::from_raw(self_ptr as *const Self) };
let ptr1 = self_weak.clone().into_raw();
let ptr2 = self_weak.into_raw();
@@ -598,6 +610,8 @@ impl Shared {
}
fn wake_shared_waker_by_ref(self_ptr: *const ()) {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let self_weak = unsafe { Weak::from_raw(self_ptr as *const Self) };
if let Some(self_arc) = Weak::upgrade(&self_weak) {
self_arc.rd_waker.wake();
@@ -607,6 +621,8 @@ impl Shared {
}
fn drop_shared_waker(self_ptr: *const ()) {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let _ = unsafe { Weak::from_raw(self_ptr as *const Self) };
}
diff --git a/ext/webgpu/src/buffer.rs b/ext/webgpu/src/buffer.rs
index 24bd98efb..f8bc213a3 100644
--- a/ext/webgpu/src/buffer.rs
+++ b/ext/webgpu/src/buffer.rs
@@ -105,6 +105,8 @@ pub async fn op_webgpu_buffer_get_map_async(
user_data: *mut u8,
) {
let sender_ptr = user_data as *mut oneshot::Sender<Result<(), AnyError>>;
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let boxed_sender = unsafe { Box::from_raw(sender_ptr) };
boxed_sender
.send(match status {
@@ -188,6 +190,8 @@ pub fn op_webgpu_buffer_get_mapped_range(
))
.map_err(|e| DomExceptionOperationError::new(&e.to_string()))?;
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let slice = unsafe {
std::slice::from_raw_parts_mut(slice_pointer, range_size as usize)
};
@@ -225,6 +229,8 @@ pub fn op_webgpu_buffer_unmap(
let size = mapped_resource.1;
if let Some(buffer) = zero_copy {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let slice = unsafe { std::slice::from_raw_parts_mut(slice_pointer, size) };
slice.copy_from_slice(&buffer);
}
diff --git a/runtime/ops/io.rs b/runtime/ops/io.rs
index 78263ce28..bef33e9fa 100644
--- a/runtime/ops/io.rs
+++ b/runtime/ops/io.rs
@@ -42,26 +42,35 @@ use {
// alive for the duration of the application since the last handle/fd
// being dropped will close the corresponding pipe.
#[cfg(unix)]
-static STDIN_HANDLE: Lazy<StdFile> =
- Lazy::new(|| unsafe { StdFile::from_raw_fd(0) });
+static STDIN_HANDLE: Lazy<StdFile> = Lazy::new(|| {
+ // SAFETY: corresponds to OS stdin
+ unsafe { StdFile::from_raw_fd(0) }
+});
#[cfg(unix)]
-static STDOUT_HANDLE: Lazy<StdFile> =
- Lazy::new(|| unsafe { StdFile::from_raw_fd(1) });
+static STDOUT_HANDLE: Lazy<StdFile> = Lazy::new(|| {
+ // SAFETY: corresponds to OS stdout
+ unsafe { StdFile::from_raw_fd(1) }
+});
#[cfg(unix)]
-static STDERR_HANDLE: Lazy<StdFile> =
- Lazy::new(|| unsafe { StdFile::from_raw_fd(2) });
+static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| {
+ // SAFETY: corresponds to OS stderr
+ unsafe { StdFile::from_raw_fd(2) }
+});
#[cfg(windows)]
-static STDIN_HANDLE: Lazy<StdFile> = Lazy::new(|| unsafe {
- StdFile::from_raw_handle(GetStdHandle(winbase::STD_INPUT_HANDLE))
+static STDIN_HANDLE: Lazy<StdFile> = Lazy::new(|| {
+ // SAFETY: corresponds to OS stdin
+ unsafe { StdFile::from_raw_handle(GetStdHandle(winbase::STD_INPUT_HANDLE)) }
});
#[cfg(windows)]
-static STDOUT_HANDLE: Lazy<StdFile> = Lazy::new(|| unsafe {
- StdFile::from_raw_handle(GetStdHandle(winbase::STD_OUTPUT_HANDLE))
+static STDOUT_HANDLE: Lazy<StdFile> = Lazy::new(|| {
+ // SAFETY: corresponds to OS stdout
+ unsafe { StdFile::from_raw_handle(GetStdHandle(winbase::STD_OUTPUT_HANDLE)) }
});
#[cfg(windows)]
-static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| unsafe {
- StdFile::from_raw_handle(GetStdHandle(winbase::STD_ERROR_HANDLE))
+static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| {
+ // SAFETY: corresponds to OS stderr
+ unsafe { StdFile::from_raw_handle(GetStdHandle(winbase::STD_ERROR_HANDLE)) }
});
pub fn init() -> Extension {
diff --git a/runtime/ops/os.rs b/runtime/ops/os.rs
index 654bbede1..dbc87daab 100644
--- a/runtime/ops/os.rs
+++ b/runtime/ops/os.rs
@@ -248,7 +248,11 @@ fn op_system_memory_info(
fn op_getgid(state: &mut OpState) -> Result<Option<u32>, AnyError> {
super::check_unstable(state, "Deno.getGid");
state.borrow_mut::<Permissions>().env.check_all()?;
- unsafe { Ok(Some(libc::getgid())) }
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ Ok(Some(libc::getgid()))
+ }
}
#[cfg(windows)]
@@ -264,7 +268,11 @@ fn op_getgid(state: &mut OpState) -> Result<Option<u32>, AnyError> {
fn op_getuid(state: &mut OpState) -> Result<Option<u32>, AnyError> {
super::check_unstable(state, "Deno.getUid");
state.borrow_mut::<Permissions>().env.check_all()?;
- unsafe { Ok(Some(libc::getuid())) }
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ Ok(Some(libc::getuid()))
+ }
}
#[cfg(windows)]
diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs
index 49f26ade4..a48cd122d 100644
--- a/runtime/ops/process.rs
+++ b/runtime/ops/process.rs
@@ -174,6 +174,8 @@ fn op_run(state: &mut OpState, run_args: RunArgs) -> Result<RunInfo, AnyError> {
c.uid(uid);
}
#[cfg(unix)]
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
c.pre_exec(|| {
libc::setgroups(0, std::ptr::null());
diff --git a/runtime/ops/spawn.rs b/runtime/ops/spawn.rs
index 7e7e2d05e..a6930b485 100644
--- a/runtime/ops/spawn.rs
+++ b/runtime/ops/spawn.rs
@@ -149,6 +149,8 @@ fn create_command(
command.uid(uid);
}
#[cfg(unix)]
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
command.pre_exec(|| {
libc::setgroups(0, std::ptr::null());
diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs
index ad152e2da..62a7717a6 100644
--- a/runtime/ops/tty.rs
+++ b/runtime/ops/tty.rs
@@ -172,12 +172,16 @@ fn op_isatty(state: &mut OpState, rid: ResourceId) -> Result<bool, AnyError> {
let handle = get_windows_handle(std_file)?;
let mut test_mode: DWORD = 0;
// If I cannot get mode out of console, it is not a console.
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
Ok(unsafe { consoleapi::GetConsoleMode(handle, &mut test_mode) != FALSE })
}
#[cfg(unix)]
{
use std::os::unix::io::AsRawFd;
let raw_fd = std_file.as_raw_fd();
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
Ok(unsafe { libc::isatty(raw_fd as libc::c_int) == 1 })
}
})?;
@@ -225,6 +229,8 @@ fn op_console_size(
use std::os::unix::io::AsRawFd;
let fd = std_file.as_raw_fd();
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
let mut size: libc::winsize = std::mem::zeroed();
if libc::ioctl(fd, libc::TIOCGWINSZ, &mut size as *mut _) != 0 {
diff --git a/runtime/permissions.rs b/runtime/permissions.rs
index be6c0c188..ab8baec89 100644
--- a/runtime/permissions.rs
+++ b/runtime/permissions.rs
@@ -1886,6 +1886,8 @@ fn permission_prompt(message: &str, name: &str) -> bool {
#[cfg(unix)]
fn clear_stdin() -> Result<(), AnyError> {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
let r = unsafe { libc::tcflush(0, libc::TCIFLUSH) };
assert_eq!(r, 0);
Ok(())
diff --git a/serde_v8/examples/basic.rs b/serde_v8/examples/basic.rs
index 81a8e6e6c..8f19e9405 100644
--- a/serde_v8/examples/basic.rs
+++ b/serde_v8/examples/basic.rs
@@ -52,6 +52,8 @@ fn main() {
println!("x = {}", x);
}
+ // SAFETY: all isolates have been destroyed, so we can now safely let V8 clean
+ // up its resources.
unsafe {
v8::V8::dispose();
}
diff --git a/serde_v8/magic/rawbytes.rs b/serde_v8/magic/rawbytes.rs
index d82e68717..2189ebfc3 100644
--- a/serde_v8/magic/rawbytes.rs
+++ b/serde_v8/magic/rawbytes.rs
@@ -87,8 +87,10 @@ mod tests {
#[test]
fn bytes_layout() {
+ // SAFETY: ensuring layout is the same
let u1: [usize; 4] =
unsafe { mem::transmute(from_static(HELLO.as_bytes())) };
+ // SAFETY: ensuring layout is the same
let u2: [usize; 4] =
unsafe { mem::transmute(bytes::Bytes::from_static(HELLO.as_bytes())) };
assert_eq!(u1[..3], u2[..3]); // Struct bytes are equal besides Vtables
diff --git a/serde_v8/serializable.rs b/serde_v8/serializable.rs
index a724f300e..abde544c7 100644
--- a/serde_v8/serializable.rs
+++ b/serde_v8/serializable.rs
@@ -97,6 +97,8 @@ impl<T: serde::Serialize + 'static> From<T> for SerializablePkg {
fn from(x: T) -> Self {
#[inline(always)]
fn tc<T, U>(src: T) -> U {
+ // SAFETY: the caller has ensured via the TypeId that the T and U types
+ // are the same.
let x = unsafe { transmute_copy(&src) };
std::mem::forget(src);
x
diff --git a/serde_v8/utils.rs b/serde_v8/utils.rs
index 427ac5f2f..d491ac093 100644
--- a/serde_v8/utils.rs
+++ b/serde_v8/utils.rs
@@ -17,6 +17,7 @@ pub fn v8_init() {
}
pub fn v8_shutdown() {
+ // SAFETY: this is safe, because all isolates have been shut down already.
unsafe {
v8::V8::dispose();
}
diff --git a/test_ffi/src/lib.rs b/test_ffi/src/lib.rs
index 5b813cd01..b4908d9cd 100644
--- a/test_ffi/src/lib.rs
+++ b/test_ffi/src/lib.rs
@@ -1,5 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+#![allow(clippy::undocumented_unsafe_blocks)]
+
use std::os::raw::c_void;
use std::thread::sleep;
use std::time::Duration;
@@ -11,23 +13,29 @@ pub extern "C" fn print_something() {
println!("something");
}
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
+/// # Safety
+///
+/// The pointer to the buffer must be valid and initalized, and the length must
+/// not be longer than the buffer's allocation.
#[no_mangle]
-pub extern "C" fn print_buffer(ptr: *const u8, len: usize) {
- let buf = unsafe { std::slice::from_raw_parts(ptr, len) };
+pub unsafe extern "C" fn print_buffer(ptr: *const u8, len: usize) {
+ let buf = std::slice::from_raw_parts(ptr, len);
println!("{:?}", buf);
}
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
+/// # Safety
+///
+/// The pointer to the buffer must be valid and initalized, and the length must
+/// not be longer than the buffer's allocation.
#[no_mangle]
-pub extern "C" fn print_buffer2(
+pub unsafe extern "C" fn print_buffer2(
ptr1: *const u8,
len1: usize,
ptr2: *const u8,
len2: usize,
) {
- let buf1 = unsafe { std::slice::from_raw_parts(ptr1, len1) };
- let buf2 = unsafe { std::slice::from_raw_parts(ptr2, len2) };
+ let buf1 = std::slice::from_raw_parts(ptr1, len1);
+ let buf2 = std::slice::from_raw_parts(ptr2, len2);
println!("{:?} {:?}", buf1, buf2);
}
@@ -87,19 +95,25 @@ pub extern "C" fn sleep_blocking(ms: u64) {
sleep(duration);
}
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
+/// # Safety
+///
+/// The pointer to the buffer must be valid and initalized, and the length must
+/// not be longer than the buffer's allocation.
#[no_mangle]
-pub extern "C" fn fill_buffer(value: u8, buf: *mut u8, len: usize) {
- let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
+pub unsafe extern "C" fn fill_buffer(value: u8, buf: *mut u8, len: usize) {
+ let buf = std::slice::from_raw_parts_mut(buf, len);
for itm in buf.iter_mut() {
*itm = value;
}
}
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
+/// # Safety
+///
+/// The pointer to the buffer must be valid and initalized, and the length must
+/// not be longer than the buffer's allocation.
#[no_mangle]
-pub extern "C" fn nonblocking_buffer(ptr: *const u8, len: usize) {
- let buf = unsafe { std::slice::from_raw_parts(ptr, len) };
+pub unsafe extern "C" fn nonblocking_buffer(ptr: *const u8, len: usize) {
+ let buf = std::slice::from_raw_parts(ptr, len);
assert_eq!(buf, vec![1, 2, 3, 4, 5, 6, 7, 8]);
}
diff --git a/tools/lint.js b/tools/lint.js
index 18be09c65..f1fa96a2c 100755
--- a/tools/lint.js
+++ b/tools/lint.js
@@ -116,6 +116,10 @@ async function clippy() {
"clippy::all",
"-D",
"clippy::await_holding_refcell_ref",
+ "-D",
+ "clippy::missing_safety_doc",
+ "-D",
+ "clippy::undocumented_unsafe_blocks",
],
stdout: "inherit",
stderr: "inherit",