Skip to content

Commit 07b7465

Browse files
authored
Add safety preconditions to std/src/alloc.rs (#330)
These contracts formalize the safety requirements that were previously only documented in comments. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent d37c183 commit 07b7465

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

.github/workflows/kani.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ jobs:
8181
- name: Run Kani Verification
8282
run: |
8383
scripts/run-kani.sh --run autoharness --kani-args \
84+
--include-pattern alloc::__default_lib_allocator:: \
8485
--include-pattern alloc::layout::Layout::from_size_align \
8586
--include-pattern ascii::ascii_char::AsciiChar::from_u8 \
8687
--include-pattern char::convert::from_u32_unchecked \

library/std/src/alloc.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,16 @@
5656
#![deny(unsafe_op_in_unsafe_fn)]
5757
#![stable(feature = "alloc_module", since = "1.28.0")]
5858

59+
#[cfg(kani)]
60+
use core::kani;
5961
use core::ptr::NonNull;
6062
use core::sync::atomic::{Atomic, AtomicPtr, Ordering};
6163
use core::{hint, mem, ptr};
6264

6365
#[stable(feature = "alloc_module", since = "1.28.0")]
6466
#[doc(inline)]
6567
pub use alloc_crate::alloc::*;
68+
use safety::requires;
6669

6770
/// The default memory allocator provided by the operating system.
6871
///
@@ -150,6 +153,10 @@ impl System {
150153
}
151154

152155
// SAFETY: Same as `Allocator::grow`
156+
#[requires(new_layout.size() >= old_layout.size())]
157+
#[requires(ptr.as_ptr().is_aligned_to(old_layout.align()))]
158+
#[requires(old_layout.size() == 0 || old_layout.align() != 0)]
159+
#[requires(new_layout.size() == 0 || new_layout.align() != 0)]
153160
#[inline]
154161
unsafe fn grow_impl(
155162
&self,
@@ -212,6 +219,7 @@ unsafe impl Allocator for System {
212219
self.alloc_impl(layout, true)
213220
}
214221

222+
#[requires(layout.size() != 0)]
215223
#[inline]
216224
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
217225
if layout.size() != 0 {
@@ -221,6 +229,7 @@ unsafe impl Allocator for System {
221229
}
222230
}
223231

232+
#[requires(new_layout.size() >= old_layout.size())]
224233
#[inline]
225234
unsafe fn grow(
226235
&self,
@@ -232,6 +241,7 @@ unsafe impl Allocator for System {
232241
unsafe { self.grow_impl(ptr, old_layout, new_layout, false) }
233242
}
234243

244+
#[requires(new_layout.size() >= old_layout.size())]
235245
#[inline]
236246
unsafe fn grow_zeroed(
237247
&self,
@@ -243,6 +253,7 @@ unsafe impl Allocator for System {
243253
unsafe { self.grow_impl(ptr, old_layout, new_layout, true) }
244254
}
245255

256+
#[requires(new_layout.size() <= old_layout.size())]
246257
#[inline]
247258
unsafe fn shrink(
248259
&self,
@@ -382,6 +393,11 @@ pub fn rust_oom(layout: Layout) -> ! {
382393
#[allow(unused_attributes)]
383394
#[unstable(feature = "alloc_internals", issue = "none")]
384395
pub mod __default_lib_allocator {
396+
#[cfg(kani)]
397+
use core::kani;
398+
399+
use safety::requires;
400+
385401
use super::{GlobalAlloc, Layout, System};
386402
// These magic symbol names are used as a fallback for implementing the
387403
// `__rust_alloc` etc symbols (see `src/liballoc/alloc.rs`) when there is
@@ -393,6 +409,7 @@ pub mod __default_lib_allocator {
393409
// linkage directives are provided as part of the current compiler allocator
394410
// ABI
395411

412+
#[requires(align.is_power_of_two())]
396413
#[rustc_std_internal_symbol]
397414
pub unsafe extern "C" fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
398415
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
@@ -403,13 +420,15 @@ pub mod __default_lib_allocator {
403420
}
404421
}
405422

423+
#[requires(align.is_power_of_two())]
406424
#[rustc_std_internal_symbol]
407425
pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) {
408426
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
409427
// `GlobalAlloc::dealloc`.
410428
unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
411429
}
412430

431+
#[requires(align.is_power_of_two())]
413432
#[rustc_std_internal_symbol]
414433
pub unsafe extern "C" fn __rdl_realloc(
415434
ptr: *mut u8,
@@ -425,6 +444,7 @@ pub mod __default_lib_allocator {
425444
}
426445
}
427446

447+
#[requires(align.is_power_of_two())]
428448
#[rustc_std_internal_symbol]
429449
pub unsafe extern "C" fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
430450
// SAFETY: see the guarantees expected by `Layout::from_size_align` and

0 commit comments

Comments
 (0)