1#[macro_use]
2pub mod util;
3
4pub mod disassemble;
5pub mod engine;
6pub mod path_exploration;
7pub mod solver;
8
9use anyhow::Context;
10pub use engine::{
11 BugFinder, RaritySimulation, RaritySimulationBug, RaritySimulationError,
12 RaritySimulationOptions, SymbolicExecutionBug, SymbolicExecutionEngine, SymbolicExecutionError,
13 SymbolicExecutionOptions,
14};
15use riscu::{load_object_file, Program};
16pub use solver::{SmtGenerationOptions, SmtType};
17use std::{fs::File, io::Write, path::Path};
18use thiserror::Error;
19
20#[derive(Debug, Error)]
21pub enum MonsterError {
22 #[error("I/O error")]
23 IoError(anyhow::Error),
24
25 #[error("preprocessing failed with error")]
26 Preprocessing(anyhow::Error),
27
28 #[error("symbolic execution stopped with error, {0}")]
29 SymbolicExecution(SymbolicExecutionError),
30
31 #[error("rarity simulation stopped with error")]
32 RaritySimulation(RaritySimulationError),
33}
34
35pub fn load_elf<P>(input: P) -> Result<Program, MonsterError>
36where
37 P: AsRef<Path>,
38{
39 load_object_file(input).map_err(|e| {
40 MonsterError::IoError(anyhow::Error::new(e).context("Failed to load object file"))
41 })
42}
43
44pub fn symbolically_execute(
45 program: &Program,
46) -> Result<Option<SymbolicExecutionBug>, MonsterError> {
47 let options = SymbolicExecutionOptions::default();
48 let solver = solver::MonsterSolver::default();
49 let strategy = path_exploration::ShortestPathStrategy::compute_for(program)
50 .map_err(MonsterError::Preprocessing)?;
51
52 symbolically_execute_with(program, &options, &strategy, &solver)
53}
54
55pub fn symbollically_execute_elf<P: AsRef<Path>>(
56 input: P,
57) -> Result<Option<SymbolicExecutionBug>, MonsterError> {
58 let program = load_elf(input)?;
59
60 symbolically_execute(&program)
61}
62
63pub fn symbolically_execute_with<Solver, Strategy>(
64 program: &Program,
65 options: &SymbolicExecutionOptions,
66 strategy: &Strategy,
67 solver: &Solver,
68) -> Result<Option<SymbolicExecutionBug>, MonsterError>
69where
70 Strategy: path_exploration::ExplorationStrategy,
71 Solver: solver::Solver,
72{
73 SymbolicExecutionEngine::new(&options, strategy, solver)
74 .search_for_bugs(&program)
75 .map_err(MonsterError::SymbolicExecution)
76}
77
78pub fn symbolically_execute_elf_with<P, Solver, Strategy>(
79 input: P,
80 options: &SymbolicExecutionOptions,
81 strategy: &Strategy,
82 solver: &Solver,
83) -> Result<Option<SymbolicExecutionBug>, MonsterError>
84where
85 P: AsRef<Path>,
86 Strategy: path_exploration::ExplorationStrategy,
87 Solver: solver::Solver,
88{
89 let program = load_elf(input)?;
90
91 symbolically_execute_with(&program, options, strategy, solver)
92}
93
94pub fn generate_smt<Strategy, W, P>(
95 input: P,
96 write: W,
97 options: &SmtGenerationOptions,
98 strategy: &Strategy,
99) -> Result<Option<SymbolicExecutionBug>, MonsterError>
100where
101 W: Write + Send + 'static,
102 Strategy: path_exploration::ExplorationStrategy,
103 P: AsRef<Path>,
104{
105 let sym_options = SymbolicExecutionOptions {
106 memory_size: options.memory_size,
107 max_exection_depth: options.max_execution_depth,
108 optimistically_prune_search_space: false,
109 };
110
111 match options.smt_type {
112 SmtType::Generic => {
113 let solver = solver::SmtWriter::new::<W>(write)
114 .context("failed to generate SMT file writer backend")
115 .map_err(MonsterError::Preprocessing)?;
116
117 symbolically_execute_elf_with(input, &sym_options, strategy, &solver)
118 }
119 #[cfg(feature = "boolector")]
120 SmtType::Boolector => {
121 let solver = solver::SmtWriter::new_for_solver::<solver::Boolector, W>(write)
122 .context("failed to generate SMT file writer backend")
123 .map_err(MonsterError::Preprocessing)?;
124
125 symbolically_execute_elf_with(input, &sym_options, strategy, &solver)
126 }
127 #[cfg(feature = "z3")]
128 SmtType::Z3 => {
129 let solver = solver::SmtWriter::new_for_solver::<solver::Z3, W>(write)
130 .context("failed to generate SMT file writer backend")
131 .map_err(MonsterError::Preprocessing)?;
132
133 symbolically_execute_elf_with(input, &sym_options, strategy, &solver)
134 }
135 }
136}
137
138pub fn generate_smt_to_file<Strategy, P>(
139 input: P,
140 output: P,
141 options: &SmtGenerationOptions,
142 strategy: &Strategy,
143) -> Result<Option<SymbolicExecutionBug>, MonsterError>
144where
145 Strategy: path_exploration::ExplorationStrategy,
146 P: AsRef<Path> + Send,
147{
148 let file = File::create(output)
149 .context("failed to generate SMT file writer")
150 .map_err(MonsterError::IoError)?;
151
152 generate_smt(input, file, options, strategy)
153}
154
155pub fn rarity_simulate(program: &Program) -> Result<Option<RaritySimulationBug>, MonsterError> {
156 rarity_simulate_with(program, &RaritySimulationOptions::default())
157}
158
159pub fn rarity_simulate_elf<P: AsRef<Path>>(
160 input: P,
161) -> Result<Option<RaritySimulationBug>, MonsterError> {
162 let program = load_elf(input)?;
163
164 rarity_simulate(&program)
165}
166
167pub fn rarity_simulate_with(
168 program: &Program,
169 options: &RaritySimulationOptions,
170) -> Result<Option<RaritySimulationBug>, MonsterError> {
171 RaritySimulation::new(&options)
172 .search_for_bugs(program)
173 .map_err(MonsterError::RaritySimulation)
174}
175
176pub fn rarity_simulate_elf_with<P>(
177 input: P,
178 options: &RaritySimulationOptions,
179) -> Result<Option<RaritySimulationBug>, MonsterError>
180where
181 P: AsRef<Path>,
182{
183 let program = load_elf(input)?;
184
185 rarity_simulate_with(&program, options)
186}