crucible/
lib.rs

1#![feature(allocator_api)]
2#![feature(core_intrinsics)]
3#![feature(crucible_intrinsics)]
4#![feature(nonzero_internals)]
5#![feature(unboxed_closures)]
6#![feature(tuple_trait)]
7#![no_std]
8
9pub mod bitvector;
10pub mod cryptol;
11pub mod method_spec;
12pub mod sym_bytes;
13pub mod symbolic;
14
15// These modules expose Crucible primitives for use within our custom version of `libstd`.  They
16// aren't meant to be used from normal symbolic tests.
17#[doc(hidden)] pub mod alloc;
18#[doc(hidden)] pub use core::crucible::any;
19#[doc(hidden)] pub mod array;
20#[doc(hidden)] pub use core::crucible::ptr;
21#[doc(hidden)] pub mod vector;
22
23pub use self::alloc::TypedAllocator;
24
25// Re-export the `Symbolic` trait, which is used to create symbolic values.
26pub use self::symbolic::Symbolic;
27
28/// Assert that a condition holds.  During symbolic testing, `crux-mir` will search for an
29/// assignment to the symbolic variables that violates an assertion.
30///
31/// This macro works just like the standard `assert!`, but currently produces better error
32/// messages.
33///
34/// If the error message uses string formatting, `crux-mir` will choose an arbitrary concrete
35/// counterexample and use its values when formatting the message.  For example,
36/// `crucible_assert!(x + y == z, "bad arithmetic: {} + {} != {}", x, y, z);` might print a message
37/// like `bad arithmetic: 1 + 2 != 4`, assuming `x`, `y`, and `z` are symbolic variables that can
38/// take on the values 1, 2, and 4..
39#[macro_export]
40macro_rules! crucible_assert {
41    ($cond:expr) => {
42        $crate::crucible_assert!($cond, stringify!($cond))
43    };
44    ($cond:expr, $fmt:expr) => {
45        $crate::crucible_assert_impl($cond, $fmt, file!(), line!(), column!());
46    };
47    ($cond:expr, $fmt:expr, $($args:tt)*) => {
48        if !$cond {
49            $crate::crucible_assert_impl(
50                false,
51                // Can't use `let` here because `format_args` takes the address of temporaries.
52                &format!("{}", $crate::concretize(format_args!($fmt, $($args)*))),
53                file!(),
54                line!(),
55                column!(),
56            );
57        }
58    };
59}
60
61/// Internal implementation detail of `crucible_assert!`.  Users should not call this directly -
62/// use the `crucible_assert!` macro instead.
63#[doc(hidden)]
64pub fn crucible_assert_impl(
65    _cond: bool,
66    _cond_str: &str,
67    _file: &'static str,
68    _line: u32,
69    _col: u32,
70) -> () {
71    ()
72}
73
74/// Assume that a condition holds.  `crux-mir` will not consider assignments to the symbolic
75/// variables that violate an assumption.
76#[macro_export]
77macro_rules! crucible_assume {
78    ($e:expr) => {
79        $crate::crucible_assume_impl($e, stringify!($e), file!(), line!(), column!())
80    };
81}
82
83/// Internal implementation detail of `crucible_assume!`.  Users should not call this directly -
84/// use the `crucible_assume!` macro instead.
85#[doc(hidden)]
86pub fn crucible_assume_impl(
87    _cond: bool,
88    _cond_str: &'static str,
89    _file: &'static str,
90    _line: u32,
91    _col: u32,
92) -> () {
93    ()
94}
95
96
97/// Assert that the current code is unreachable.  This is similar to the standard `unreachable!()`
98/// macro, but uses `crucible_assert!` internally.
99#[macro_export]
100macro_rules! crucible_assert_unreachable {
101    () => {{
102        $crate::crucible_assert!(false);
103        unreachable!()
104    }};
105}
106
107/// Assume that the current code is unreachable.  This is similar to `crucible_assume!(false)`, but
108/// also returns `!`, so it can be used in positions where a return value is expected.
109#[macro_export]
110macro_rules! crucible_assume_unreachable {
111    () => {{
112        $crate::crucible_assume!(false);
113        unreachable!()
114    }};
115}
116
117
118/// Given a symbolic value, choose an arbitrary instance that satisfies the current path condition.
119/// This function operates recursively: a call to `concretize(&(x, y))` (where `x` and `y` are
120/// symbolic integers) will produce a concrete result like `&(1, 2)`.
121///
122/// This function is highly magical, and should only be used if you understand its override
123/// implementation (`concretize` in `Mir/Overrides.hs`).  It's mainly intended for use in printing
124/// counterexamples, where the current execution path is terminated shortly after the
125/// `concretize()` call.  It's probably unwise to use this on paths that will later be joined with
126/// others.
127pub fn concretize<T>(x: T) -> T {
128    x
129}
130
131/// Install `g` as an override for `f`.
132pub fn override_<F, G>(f: F, g: G) {
133    unimplemented!("crucible::override_");
134}
135
136/// Print a string during symbolic execution.  The string must be concrete.
137///
138/// Due to the way crux-mir explores paths through the program, these prints may execute in an
139/// unusual order.  For example, `if cond { print_str("foo") } else { print_str("bar") }` may print
140/// both `foo` and `bar` in some cases.
141pub fn print_str(s: &str) {
142    unimplemented!("print_str");
143}
144
145/// Print a what4 expression to stderr.  `T` must have a primitive/base type for its Crucible
146/// representation.
147pub fn dump_what4<T>(desc: &str, x: T) {
148    unimplemented!("dump_what4");
149}
150
151/// Print a Crucible `RegValue` to stderr.  Most `TypeRepr`s used by crucible-mir are supported,
152/// but not all; if `T` uses an unsupported `TypeRepr`, this may print `[unsupported]` or throw an
153/// error.
154pub fn dump_rv<T>(desc: &str, x: T) {
155    unimplemented!("dump_rv");
156}
157
158// Some older test cases still use these functions.
159#[deprecated(note = "call i8::symbolic instead")]
160pub fn crucible_i8(name: &'static str) -> i8 { Symbolic::symbolic(name) }
161#[deprecated(note = "call i16::symbolic instead")]
162pub fn crucible_i16(name: &'static str) -> i16 { Symbolic::symbolic(name) }
163#[deprecated(note = "call i32::symbolic instead")]
164pub fn crucible_i32(name: &'static str) -> i32 { Symbolic::symbolic(name) }
165#[deprecated(note = "call i64::symbolic instead")]
166pub fn crucible_i64(name: &'static str) -> i64 { Symbolic::symbolic(name) }
167#[deprecated(note = "call u8::symbolic instead")]
168pub fn crucible_u8(name: &'static str) -> u8 { Symbolic::symbolic(name) }
169#[deprecated(note = "call u16::symbolic instead")]
170pub fn crucible_u16(name: &'static str) -> u16 { Symbolic::symbolic(name) }
171#[deprecated(note = "call u32::symbolic instead")]
172pub fn crucible_u32(name: &'static str) -> u32 { Symbolic::symbolic(name) }
173#[deprecated(note = "call u64::symbolic instead")]
174pub fn crucible_u64(name: &'static str) -> u64 { Symbolic::symbolic(name) }
175
176/// This function is overridden and used in a few test cases that check override functionality.
177#[doc(hidden)]
178pub fn one() -> u8 { unimplemented!() }