Skip to content

Commit 9684fc1

Browse files
author
Fedor Ryabinin
committed
Generated contracts.
1 parent 099ad08 commit 9684fc1

21 files changed

Lines changed: 489 additions & 0 deletions

File tree

library/alloc/src/collections/btree/navigate.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
#![feature(ub_checks)]
2+
use safety::{ensures,requires};
3+
#[cfg(kani)]
4+
#[unstable(feature="kani", issue="none")]
5+
use core::kani;
6+
#[allow(unused_imports)]
7+
#[unstable(feature = "ub_checks", issue = "none")]
8+
use core::ub_checks::*;
9+
110
use core::borrow::Borrow;
211
use core::ops::RangeBounds;
312
use core::{hint, ptr};
@@ -157,23 +166,27 @@ impl<BorrowType, K, V> LazyLeafRange<BorrowType, K, V> {
157166

158167
impl<'a, K, V> LazyLeafRange<marker::Immut<'a>, K, V> {
159168
#[inline]
169+
#[requires(self.front.is_some())]
160170
pub(super) unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
161171
unsafe { self.init_front().unwrap().next_unchecked() }
162172
}
163173

164174
#[inline]
175+
#[requires(self.back.is_some())]
165176
pub(super) unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
166177
unsafe { self.init_back().unwrap().next_back_unchecked() }
167178
}
168179
}
169180

170181
impl<'a, K, V> LazyLeafRange<marker::ValMut<'a>, K, V> {
171182
#[inline]
183+
#[requires(self.front.is_some())]
172184
pub(super) unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
173185
unsafe { self.init_front().unwrap().next_unchecked() }
174186
}
175187

176188
#[inline]
189+
#[requires(self.back.is_some())]
177190
pub(super) unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
178191
unsafe { self.init_back().unwrap().next_back_unchecked() }
179192
}
@@ -190,6 +203,7 @@ impl<K, V> LazyLeafRange<marker::Dying, K, V> {
190203
}
191204

192205
#[inline]
206+
#[requires(self.front.is_some())]
193207
pub(super) unsafe fn deallocating_next_unchecked<A: Allocator + Clone>(
194208
&mut self,
195209
alloc: A,
@@ -200,6 +214,7 @@ impl<K, V> LazyLeafRange<marker::Dying, K, V> {
200214
}
201215

202216
#[inline]
217+
#[requires(self.back.is_some())]
203218
pub(super) unsafe fn deallocating_next_back_unchecked<A: Allocator + Clone>(
204219
&mut self,
205220
alloc: A,

library/alloc/src/collections/linked_list.rs

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,17 @@
1010
//! [`Vec`]: crate::vec::Vec
1111
//! [`VecDeque`]: super::vec_deque::VecDeque
1212
13+
#![feature(ub_checks)]
1314
#![stable(feature = "rust1", since = "1.0.0")]
1415

16+
use safety::{ensures,requires};
17+
#[cfg(kani)]
18+
#[unstable(feature="kani", issue="none")]
19+
use core::kani;
20+
#[allow(unused_imports)]
21+
#[unstable(feature = "ub_checks", issue = "none")]
22+
use core::ub_checks::*;
23+
1524
use core::cmp::Ordering;
1625
use core::hash::{Hash, Hasher};
1726
use core::iter::FusedIterator;
@@ -170,6 +179,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
170179
/// `node` must point to a valid node that was boxed and leaked using the list's allocator.
171180
/// This method takes ownership of the node, so the pointer should not be used again.
172181
#[inline]
182+
#[requires(can_dereference(node.as_ptr()))]
173183
unsafe fn push_front_node(&mut self, node: NonNull<Node<T>>) {
174184
// This method takes care not to create mutable references to whole nodes,
175185
// to maintain validity of aliasing pointers into `element`.
@@ -215,6 +225,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
215225
/// `node` must point to a valid node that was boxed and leaked using the list's allocator.
216226
/// This method takes ownership of the node, so the pointer should not be used again.
217227
#[inline]
228+
#[requires(can_dereference(node.as_ptr()))]
218229
unsafe fn push_back_node(&mut self, node: NonNull<Node<T>>) {
219230
// This method takes care not to create mutable references to whole nodes,
220231
// to maintain validity of aliasing pointers into `element`.
@@ -261,6 +272,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
261272
/// This method takes care not to create mutable references to `element`, to
262273
/// maintain validity of aliasing pointers.
263274
#[inline]
275+
#[requires(can_dereference(node.as_ptr()))]
264276
unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {
265277
let node = unsafe { node.as_mut() }; // this one is ours now, we can create an &mut.
266278

@@ -284,6 +296,10 @@ impl<T, A: Allocator> LinkedList<T, A> {
284296
///
285297
/// Warning: this will not check that the provided node belongs to the two existing lists.
286298
#[inline]
299+
#[requires(can_dereference(splice_start.as_ptr()))]
300+
#[requires(can_dereference(splice_end.as_ptr()))]
301+
#[requires(existing_prev.map_or(true, |prev| can_dereference(prev.as_ptr())))]
302+
#[requires(existing_next.map_or(true, |next| can_dereference(next.as_ptr())))]
287303
unsafe fn splice_nodes(
288304
&mut self,
289305
existing_prev: Option<NonNull<Node<T>>>,
@@ -318,6 +334,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
318334

319335
/// Detaches all nodes from a linked list as a series of nodes.
320336
#[inline]
337+
#[requires(self.head.is_some())]
321338
fn detach_all_nodes(mut self) -> Option<(NonNull<Node<T>>, NonNull<Node<T>>, usize)> {
322339
let head = self.head.take();
323340
let tail = self.tail.take();
@@ -334,6 +351,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
334351
}
335352

336353
#[inline]
354+
#[requires(at <= self.len)]
337355
unsafe fn split_off_before_node(
338356
&mut self,
339357
split_node: Option<NonNull<Node<T>>>,
@@ -377,6 +395,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
377395
}
378396

379397
#[inline]
398+
#[requires(at <= self.len)]
380399
unsafe fn split_off_after_node(
381400
&mut self,
382401
split_node: Option<NonNull<Node<T>>>,
@@ -2205,3 +2224,177 @@ unsafe impl<T: Send, A: Allocator + Send> Send for CursorMut<'_, T, A> {}
22052224

22062225
#[unstable(feature = "linked_list_cursors", issue = "58533")]
22072226
unsafe impl<T: Sync, A: Allocator + Sync> Sync for CursorMut<'_, T, A> {}
2227+
#[cfg(kani)]
2228+
mod verify {
2229+
use super::*;
2230+
#[cfg(kani)]
2231+
#[kani::proof_for_contract(LinkedList::push_front_node)]
2232+
fn proof_for_push_front_node() {
2233+
// Create a new linked list
2234+
let mut list: LinkedList<i32> = LinkedList::new();
2235+
2236+
// Create a new node with a value
2237+
let value = kani::any::<i32>();
2238+
let node_box = Box::new(Node::new(value));
2239+
let node_ptr = NonNull::from(Box::leak(node_box));
2240+
2241+
// Call the function with the valid node pointer
2242+
unsafe {
2243+
list.push_front_node(node_ptr);
2244+
}
2245+
}
2246+
2247+
#[cfg(kani)]
2248+
#[kani::proof_for_contract(LinkedList::push_back_node)]
2249+
fn proof_for_push_back_node() {
2250+
// Create a new linked list
2251+
let mut list: LinkedList<i32> = LinkedList::new();
2252+
2253+
// Create a new node with a value
2254+
let value = kani::any::<i32>();
2255+
let node_box = Box::new(Node::new(value));
2256+
let node_ptr = NonNull::from(Box::leak(node_box));
2257+
2258+
// Call the function with the valid node pointer
2259+
unsafe {
2260+
list.push_back_node(node_ptr);
2261+
}
2262+
}
2263+
2264+
#[cfg(kani)]
2265+
#[kani::proof_for_contract(LinkedList::unlink_node)]
2266+
fn proof_for_unlink_node() {
2267+
// Create a new linked list with one element
2268+
let mut list: LinkedList<i32> = LinkedList::new();
2269+
2270+
// Add a node to the list so we can unlink it
2271+
let value = kani::any::<i32>();
2272+
list.push_back(value);
2273+
2274+
// Get the node pointer from the list
2275+
let node_ptr = list.head.unwrap();
2276+
2277+
// Call the function with the valid node pointer
2278+
unsafe {
2279+
list.unlink_node(node_ptr);
2280+
}
2281+
}
2282+
2283+
#[cfg(kani)]
2284+
#[kani::proof_for_contract(LinkedList::splice_nodes)]
2285+
fn proof_for_splice_nodes() {
2286+
// Create two linked lists
2287+
let mut target_list: LinkedList<i32> = LinkedList::new();
2288+
let mut source_list: LinkedList<i32> = LinkedList::new();
2289+
2290+
// Add some elements to both lists
2291+
target_list.push_back(1);
2292+
target_list.push_back(2);
2293+
2294+
source_list.push_back(10);
2295+
source_list.push_back(20);
2296+
2297+
// Get pointers to nodes in the target list
2298+
let existing_prev = target_list.head;
2299+
let existing_next = target_list.tail;
2300+
2301+
// Get pointers to the start and end of the source list
2302+
let splice_start = source_list.head.unwrap();
2303+
let splice_end = source_list.tail.unwrap();
2304+
let splice_length = source_list.len;
2305+
2306+
// Detach the nodes from source_list to avoid double-free
2307+
let _ = source_list.detach_all_nodes();
2308+
2309+
// Call the function with the valid node pointers
2310+
unsafe {
2311+
target_list.splice_nodes(
2312+
existing_prev,
2313+
existing_next,
2314+
splice_start,
2315+
splice_end,
2316+
splice_length,
2317+
);
2318+
}
2319+
}
2320+
2321+
#[cfg(kani)]
2322+
#[kani::proof_for_contract(LinkedList::split_off_after_node)]
2323+
fn proof_for_split_off_after_node() {
2324+
// Create a linked list with a few elements
2325+
let mut list: LinkedList<i32> = LinkedList::new();
2326+
2327+
// Add some elements to the list
2328+
list.push_back(1);
2329+
list.push_back(2);
2330+
list.push_back(3);
2331+
2332+
// Get the length of the list
2333+
let len = list.len;
2334+
2335+
// Choose a valid split point that satisfies at <= self.len
2336+
let at = if len > 0 {
2337+
kani::any::<usize>() % (len + 1)
2338+
} else {
2339+
0
2340+
};
2341+
2342+
// For simplicity, use None as the split_node
2343+
// This is valid for the contract which only requires at <= self.len
2344+
let split_node = None;
2345+
2346+
// Call the function with the valid parameters
2347+
unsafe {
2348+
let _second_part = list.split_off_after_node(split_node, at);
2349+
}
2350+
}
2351+
2352+
#[cfg(kani)]
2353+
#[kani::proof_for_contract(LinkedList::split_off_before_node)]
2354+
fn proof_for_split_off_before_node() {
2355+
// Create a linked list with a few elements
2356+
let mut list: LinkedList<i32> = LinkedList::new();
2357+
2358+
// Add some elements to the list
2359+
list.push_back(1);
2360+
list.push_back(2);
2361+
list.push_back(3);
2362+
2363+
// Get the length of the list
2364+
let len = list.len;
2365+
2366+
// Choose a valid split point that satisfies at <= self.len
2367+
let at = if len > 0 {
2368+
kani::any::<usize>() % (len + 1)
2369+
} else {
2370+
0
2371+
};
2372+
2373+
// For simplicity, use None as the split_node
2374+
// This is valid for the contract which only requires at <= self.len
2375+
let split_node = None;
2376+
2377+
// Call the function with the valid parameters
2378+
unsafe {
2379+
let _first_part = list.split_off_before_node(split_node, at);
2380+
}
2381+
}
2382+
2383+
#[cfg(kani)]
2384+
#[kani::proof_for_contract(LinkedList::detach_all_nodes)]
2385+
fn proof_for_detach_all_nodes() {
2386+
// Create a linked list with at least one element to satisfy the precondition
2387+
let mut list: LinkedList<i32> = LinkedList::new();
2388+
2389+
// Add an element to ensure self.head.is_some()
2390+
list.push_back(kani::any::<i32>());
2391+
2392+
// Optionally add more elements
2393+
if kani::any() {
2394+
list.push_back(kani::any::<i32>());
2395+
}
2396+
2397+
// Call the function
2398+
let _result = list.detach_all_nodes();
2399+
}
2400+
}

library/alloc/src/ffi/c_str.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
//! [`CString`] and its related types.
22
3+
#![feature(ub_checks)]
4+
use safety::{ensures,requires};
5+
#[cfg(kani)]
6+
#[unstable(feature="kani", issue="none")]
7+
use core::kani;
8+
#[allow(unused_imports)]
9+
#[unstable(feature = "ub_checks", issue = "none")]
10+
use core::ub_checks::*;
11+
312
use core::borrow::Borrow;
413
use core::ffi::{CStr, c_char};
514
use core::num::NonZero;
@@ -394,6 +403,10 @@ impl CString {
394403
/// ```
395404
#[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `CString`"]
396405
#[stable(feature = "cstr_memory", since = "1.4.0")]
406+
// Note: This function has complex safety requirements that cannot be fully expressed as preconditions
407+
#[requires(ptr != core::ptr::null_mut())]
408+
#[requires(can_dereference(ptr.cast::<u8>()))]
409+
#[requires(can_dereference(ptr as *const c_char))]
397410
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
398411
// SAFETY: This is called with a pointer that was obtained from a call
399412
// to `CString::into_raw` and the length has not been modified. As such,

0 commit comments

Comments
 (0)