1#[derive(Debug)]
2pub enum Error {
3 NoAuditData,
4 InputLimitExceeded,
5 OutputLimitExceeded,
6 Io(std::io::Error),
7 BinaryParsing(auditable_extract::Error),
8 Decompression(DecompressError),
9 #[cfg(feature = "serde")]
10 Json(serde_json::Error),
11 Utf8(std::str::Utf8Error),
12}
13
14impl std::fmt::Display for Error {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 Error::NoAuditData => write!(f, "No audit data found in the binary! Was it built with 'cargo auditable'?"),
18 Error::InputLimitExceeded => write!(f, "The input file is too large. Increase the input size limit to scan it."),
19 Error::OutputLimitExceeded => write!(f, "Audit data size is over the specified limit. Increase the output size limit to scan it."),
20 Error::Io(e) => write!(f, "Failed to read the binary: {e}"),
21 Error::BinaryParsing(e) => write!(f, "Failed to parse the binary: {e}"),
22 Error::Decompression(e) => write!(f, "Failed to decompress audit data: {e}"),
23 #[cfg(feature = "serde")]
24 Error::Json(e) => write!(f, "Failed to deserialize audit data from JSON: {e}"),
25 Error::Utf8(e) => write!(f, "Invalid UTF-8 in audit data: {e}"),
26 }
27 }
28}
29
30impl std::error::Error for Error {
31 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
32 match self {
33 Error::NoAuditData => None,
34 Error::InputLimitExceeded => None,
35 Error::OutputLimitExceeded => None,
36 Error::Io(e) => Some(e),
37 Error::BinaryParsing(e) => Some(e),
38 Error::Decompression(e) => Some(e),
39 #[cfg(feature = "serde")]
40 Error::Json(e) => Some(e),
41 Error::Utf8(e) => Some(e),
42 }
43 }
44}
45
46impl From<std::io::Error> for Error {
47 fn from(e: std::io::Error) -> Self {
48 Self::Io(e)
49 }
50}
51
52impl From<auditable_extract::Error> for Error {
53 fn from(e: auditable_extract::Error) -> Self {
54 match e {
55 auditable_extract::Error::NoAuditData => Error::NoAuditData,
56 other_err => Self::BinaryParsing(other_err),
57 }
58 }
59}
60
61impl From<DecompressError> for Error {
62 fn from(e: DecompressError) -> Self {
63 match e.status {
64 TINFLStatus::HasMoreOutput => Error::OutputLimitExceeded,
65 _ => Error::Decompression(e),
66 }
67 }
68}
69
70impl From<std::string::FromUtf8Error> for Error {
71 fn from(e: std::string::FromUtf8Error) -> Self {
72 Self::Utf8(e.utf8_error())
73 }
74}
75
76#[cfg(feature = "serde")]
77impl From<serde_json::Error> for Error {
78 fn from(e: serde_json::Error) -> Self {
79 Self::Json(e)
80 }
81}
82
83#[derive(Debug)]
88pub struct DecompressError {
89 pub status: TINFLStatus,
91 pub output: Vec<u8>,
93}
94
95impl std::fmt::Display for DecompressError {
96 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
97 f.write_str(match self.status {
98 TINFLStatus::FailedCannotMakeProgress => "Truncated input stream",
99 TINFLStatus::BadParam => "Invalid output buffer size",
100 TINFLStatus::Adler32Mismatch => "Adler32 checksum mismatch",
101 TINFLStatus::Failed => "Invalid input data",
102 TINFLStatus::Done => unreachable!(),
103 TINFLStatus::NeedsMoreInput => "Truncated input stream",
104 TINFLStatus::HasMoreOutput => "Output size exceeded the specified limit",
105 })
106 }
107}
108
109impl std::error::Error for DecompressError {}
110
111impl DecompressError {
112 pub(crate) fn from_miniz(err: miniz_oxide::inflate::DecompressError) -> Self {
113 Self {
114 status: TINFLStatus::from_miniz(err.status),
115 output: err.output,
116 }
117 }
118}
119
120#[repr(i8)]
121#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
122pub enum TINFLStatus {
123 FailedCannotMakeProgress,
124 BadParam,
125 Adler32Mismatch,
126 Failed,
127 Done,
128 NeedsMoreInput,
129 HasMoreOutput,
130}
131
132impl TINFLStatus {
133 pub(crate) fn from_miniz(status: miniz_oxide::inflate::TINFLStatus) -> Self {
134 use miniz_oxide::inflate;
135 match status {
136 inflate::TINFLStatus::FailedCannotMakeProgress => Self::FailedCannotMakeProgress,
137 inflate::TINFLStatus::BadParam => Self::BadParam,
138 inflate::TINFLStatus::Adler32Mismatch => Self::Adler32Mismatch,
139 inflate::TINFLStatus::Failed => Self::Failed,
140 inflate::TINFLStatus::Done => Self::Done,
141 inflate::TINFLStatus::NeedsMoreInput => Self::NeedsMoreInput,
142 inflate::TINFLStatus::HasMoreOutput => Self::HasMoreOutput,
143 }
144 }
145}