-
Notifications
You must be signed in to change notification settings - Fork 66
Challenge 27: Verify safety of Arc functions #575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4528,3 +4528,361 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc<T, A> { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(kani)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[unstable(feature = "kani", issue = "none")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mod verify { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use core::any::Any; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use core::kani; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use core::mem::MaybeUninit; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::alloc::Global; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::sync::{Arc, Weak}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // === UNSAFE (12 — all required) === | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[kani::proof] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn verify_assume_init_single() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a: Arc<MaybeUninit<i32>> = Arc::new(MaybeUninit::new(42)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = unsafe { a.assume_init() }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(*a == 42); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[kani::proof] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn verify_assume_init_slice() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut a: Arc<[MaybeUninit<i32>]> = Arc::new_uninit_slice(3); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let s = Arc::get_mut(&mut a).unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s[0].write(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s[1].write(2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s[2].write(3); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = unsafe { a.assume_init() }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(a.len() == 3); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[kani::proof] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn verify_from_raw() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = Arc::new(42i32); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let raw = Arc::into_raw(a); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = unsafe { Arc::from_raw(raw) }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(*a == 42); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[kani::proof] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn verify_from_raw_in() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = Arc::new_in(42i32, Global); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let (raw, alloc) = Arc::into_raw_with_allocator(a); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = unsafe { Arc::from_raw_in(raw, alloc) }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(*a == 42); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[kani::proof] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn verify_increment_strong_count() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = Arc::new(42i32); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ptr = Arc::as_ptr(&a); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unsafe { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Arc::increment_strong_count(ptr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a2 = unsafe { Arc::from_raw(ptr) }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(*a2 == 42); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[kani::proof] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn verify_increment_strong_count_in() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a = Arc::new_in(42i32, Global); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ptr = Arc::as_ptr(&a); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unsafe { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Arc::increment_strong_count_in(ptr, Global); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let a2 = unsafe { Arc::from_raw_in(ptr, Global) }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(*a2 == 42); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+4581
to
+4597
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ptr = Arc::as_ptr(&a); | |
| unsafe { | |
| Arc::increment_strong_count(ptr); | |
| } | |
| let a2 = unsafe { Arc::from_raw(ptr) }; | |
| assert!(*a2 == 42); | |
| } | |
| #[kani::proof] | |
| fn verify_increment_strong_count_in() { | |
| let a = Arc::new_in(42i32, Global); | |
| let ptr = Arc::as_ptr(&a); | |
| unsafe { | |
| Arc::increment_strong_count_in(ptr, Global); | |
| } | |
| let a2 = unsafe { Arc::from_raw_in(ptr, Global) }; | |
| assert!(*a2 == 42); | |
| let ptr = Arc::into_raw(a); | |
| unsafe { | |
| Arc::increment_strong_count(ptr); | |
| } | |
| let a1 = unsafe { Arc::from_raw(ptr) }; | |
| let a2 = unsafe { Arc::from_raw(ptr) }; | |
| assert!(*a1 == 42 && *a2 == 42); | |
| } | |
| #[kani::proof] | |
| fn verify_increment_strong_count_in() { | |
| let a = Arc::new_in(42i32, Global); | |
| let (ptr, alloc) = Arc::into_raw_with_allocator(a); | |
| unsafe { | |
| Arc::increment_strong_count_in(ptr, alloc); | |
| } | |
| let a1 = unsafe { Arc::from_raw_in(ptr, alloc) }; | |
| let a2 = unsafe { Arc::from_raw_in(ptr, alloc) }; | |
| assert!(*a1 == 42 && *a2 == 42); |
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arc::decrement_strong_count’s safety contract requires that ptr was obtained through Arc::into_raw. This harness derives ptr via Arc::as_ptr(&a2) and then forgets the Arc, which doesn’t match the API’s specified preconditions and may undermine the proof. Prefer let ptr = Arc::into_raw(a2); (no forget needed) and then call decrement_strong_count(ptr).
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arc::decrement_strong_count_in requires ptr to originate from Arc::into_raw_with_allocator for the same allocator passed in. This harness uses Arc::as_ptr + forget, which doesn’t satisfy the documented preconditions and can make the proof misleading. Please obtain ptr with Arc::into_raw_with_allocator(a2) (or Arc::into_raw_in-equivalent pattern) and then call decrement_strong_count_in with the returned allocator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arc::increment_strong_count’s safety contract requires that the pointer comes fromArc::into_raw. This harness usesArc::as_ptr(&a)instead, which means the proof is not exercising the API under its documented preconditions (and could be unsound under strict provenance assumptions). Consider obtainingptrviaArc::into_raw(...)(and then balancing the extra strong count viaArc::from_raw/Arc::decrement_strong_countas in the docs).