diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/async_cancel.rs | 25 | ||||
-rw-r--r-- | core/async_cell.rs | 34 | ||||
-rw-r--r-- | core/bindings.rs | 4 | ||||
-rw-r--r-- | core/inspector.rs | 13 | ||||
-rw-r--r-- | core/modules.rs | 1 | ||||
-rw-r--r-- | core/ops.rs | 2 | ||||
-rw-r--r-- | core/ops_metrics.rs | 5 | ||||
-rw-r--r-- | core/resources.rs | 2 | ||||
-rw-r--r-- | core/runtime.rs | 5 |
9 files changed, 86 insertions, 5 deletions
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) } |