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!() }