libafl_fandango_pyo3/fandango/
mod.rs1use std::ffi::NulError;
2
3use pyo3::PyErr;
4use pyo3::prelude::*;
5
6pub(crate) mod inprocess;
7pub(crate) mod subprocess;
8
9pub use inprocess::FandangoInprocessModule;
10pub use subprocess::{FandangoSubprocessInitIpc, FandangoSubprocessModule};
11
12#[deprecated(
13 since = "0.4.0",
14 note = "Explicitly use FandangoInprocessModule or FandangoSubprocessModule instead"
15)]
16pub type FandangoPythonModule = FandangoInprocessModule;
17#[deprecated(since = "0.4.0", note = "Renamed to FandangoModuleInitError")]
18pub type FandangoPythonModuleInitError = FandangoModuleInitError;
19
20pub trait FandangoClient {
21 fn next_input(&mut self) -> Result<Vec<u8>, String>;
22 fn parse_input(&mut self, input: &[u8]) -> Result<u32, String>;
23}
24
25#[derive(Debug)]
26pub enum FandangoModuleInitError {
27 ModuleNotFoundError(PyErr, String),
28 PyErr(PyErr, String),
29 FilePathError(String),
30 ReadFileError(String),
31 EncodingError(NulError),
32 SubprocessIpc(FandangoSubprocessInitIpc),
34}
35
36impl FandangoModuleInitError {
37 pub fn format_report(&self) -> String {
42 match self {
43 Self::ModuleNotFoundError(err, tb) => {
44 Self::format_py_err_pair(err, tb, "Module not found")
45 }
46 Self::PyErr(err, tb) => Self::format_py_err_pair(err, tb, "Python error"),
47 Self::FilePathError(s) => s.clone(),
48 Self::ReadFileError(s) => s.clone(),
49 Self::EncodingError(e) => format!("Invalid string data (embedded NUL): {e}"),
50 Self::SubprocessIpc(e) => e.to_string(),
51 }
52 }
53
54 fn format_py_err_pair(err: &PyErr, tb: &str, label: &str) -> String {
55 Python::with_gil(|_| {
56 let head = err.to_string();
57 let tb = tb.trim();
58 let tb_useful = !tb.is_empty() && tb != "No traceback available";
59 if tb_useful {
60 format!("{label}: {head}\n\n{tb}")
61 } else {
62 format!("{label}: {head}")
63 }
64 })
65 }
66}
67
68impl std::fmt::Display for FandangoModuleInitError {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 write!(f, "{}", self.format_report())
71 }
72}
73
74impl std::error::Error for FandangoModuleInitError {
75 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
76 match self {
77 Self::EncodingError(e) => Some(e),
78 Self::PyErr(e, _) | Self::ModuleNotFoundError(e, _) => e.source(),
79 Self::FilePathError(_) | Self::ReadFileError(_) => None,
80 Self::SubprocessIpc(e) => std::error::Error::source(e),
81 }
82 }
83}