Skip to content

Commit 1bf01fd

Browse files
Yenyun035yew005rajathkotyal
authored
Contracts & Harnesses for unchecked_add (rust-lang#91)
Towards rust-lang#59 * Added contracts for `unchecked_add` (located in `library/core/src/num/int_macros.rs` and `uint_macros.rs`) * Added a harness for `unchecked_add` of each integer type * `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `u8`, `u16`, `u32`, `u64`, `u128`, `usize` --- 12 harnesses in total. --------- Co-authored-by: yew005 <[email protected]> Co-authored-by: Rajath Kotyal <[email protected]> Co-authored-by: rajathmCMU <[email protected]>
1 parent 024d84b commit 1bf01fd

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

library/core/src/num/int_macros.rs

+1
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ macro_rules! int_impl {
511511
without modifying the original"]
512512
#[inline(always)]
513513
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
514+
#[requires(!self.overflowing_add(rhs).1)]
514515
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
515516
assert_unsafe_precondition!(
516517
check_language_ub,

library/core/src/num/mod.rs

+74
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
use crate::str::FromStr;
66
use crate::ub_checks::assert_unsafe_precondition;
77
use crate::{ascii, intrinsics, mem};
8+
use safety::requires;
9+
10+
#[cfg(kani)]
11+
use crate::kani;
812

913
// Used because the `?` operator is not allowed in a const context.
1014
macro_rules! try_opt {
@@ -1581,3 +1585,73 @@ from_str_radix_size_impl! { i16 isize, u16 usize }
15811585
from_str_radix_size_impl! { i32 isize, u32 usize }
15821586
#[cfg(target_pointer_width = "64")]
15831587
from_str_radix_size_impl! { i64 isize, u64 usize }
1588+
1589+
#[cfg(kani)]
1590+
#[unstable(feature = "kani", issue = "none")]
1591+
mod verify {
1592+
use super::*;
1593+
1594+
macro_rules! generate_unchecked_math_harness {
1595+
($type:ty, $method:ident, $harness_name:ident) => {
1596+
#[kani::proof_for_contract($type::$method)]
1597+
pub fn $harness_name() {
1598+
let num1: $type = kani::any::<$type>();
1599+
let num2: $type = kani::any::<$type>();
1600+
1601+
unsafe {
1602+
num1.$method(num2);
1603+
}
1604+
}
1605+
}
1606+
}
1607+
1608+
macro_rules! generate_unchecked_shift_harness {
1609+
($type:ty, $method:ident, $harness_name:ident) => {
1610+
#[kani::proof_for_contract($type::$method)]
1611+
pub fn $harness_name() {
1612+
let num1: $type = kani::any::<$type>();
1613+
let num2: u32 = kani::any::<u32>();
1614+
1615+
unsafe {
1616+
num1.$method(num2);
1617+
}
1618+
}
1619+
}
1620+
}
1621+
1622+
macro_rules! generate_unchecked_neg_harness {
1623+
($type:ty, $harness_name:ident) => {
1624+
#[kani::proof_for_contract($type::unchecked_neg)]
1625+
pub fn $harness_name() {
1626+
let num1: $type = kani::any::<$type>();
1627+
1628+
unsafe {
1629+
num1.unchecked_neg();
1630+
}
1631+
}
1632+
}
1633+
}
1634+
1635+
// `unchecked_add` proofs
1636+
//
1637+
// Target types:
1638+
// i{8,16,32,64,128, size} and u{8,16,32,64,128, size} -- 12 types in total
1639+
//
1640+
// Target contracts:
1641+
// #[requires(!self.overflowing_add(rhs).1)]
1642+
//
1643+
// Target function:
1644+
// pub const unsafe fn unchecked_add(self, rhs: Self) -> Self
1645+
generate_unchecked_math_harness!(i8, unchecked_add, checked_unchecked_add_i8);
1646+
generate_unchecked_math_harness!(i16, unchecked_add, checked_unchecked_add_i16);
1647+
generate_unchecked_math_harness!(i32, unchecked_add, checked_unchecked_add_i32);
1648+
generate_unchecked_math_harness!(i64, unchecked_add, checked_unchecked_add_i64);
1649+
generate_unchecked_math_harness!(i128, unchecked_add, checked_unchecked_add_i128);
1650+
generate_unchecked_math_harness!(isize, unchecked_add, checked_unchecked_add_isize);
1651+
generate_unchecked_math_harness!(u8, unchecked_add, checked_unchecked_add_u8);
1652+
generate_unchecked_math_harness!(u16, unchecked_add, checked_unchecked_add_u16);
1653+
generate_unchecked_math_harness!(u32, unchecked_add, checked_unchecked_add_u32);
1654+
generate_unchecked_math_harness!(u64, unchecked_add, checked_unchecked_add_u64);
1655+
generate_unchecked_math_harness!(u128, unchecked_add, checked_unchecked_add_u128);
1656+
generate_unchecked_math_harness!(usize, unchecked_add, checked_unchecked_add_usize);
1657+
}

library/core/src/num/uint_macros.rs

+1
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ macro_rules! uint_impl {
558558
without modifying the original"]
559559
#[inline(always)]
560560
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
561+
#[requires(!self.overflowing_add(rhs).1)]
561562
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
562563
assert_unsafe_precondition!(
563564
check_language_ub,

0 commit comments

Comments
 (0)