1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
mod compile;
pub use self::compile::*;
use std::error;
use std::fmt;
use std::os::raw::c_int;
use crate::ERROR_CALLBACK_ERROR;
use crate::ERROR_CORRUPT_FILE;
use crate::ERROR_COULD_NOT_ATTACH_TO_PROCESS;
use crate::ERROR_COULD_NOT_MAP_FILE;
use crate::ERROR_COULD_NOT_OPEN_FILE;
use crate::ERROR_INSUFFICIENT_MEMORY;
use crate::ERROR_INTERNAL_FATAL_ERROR;
use crate::ERROR_INVALID_FILE;
use crate::ERROR_SCAN_TIMEOUT;
use crate::ERROR_SUCCESS;
use crate::ERROR_SYNTAX_ERROR;
use crate::ERROR_TOO_MANY_MATCHES;
use crate::ERROR_UNSUPPORTED_FILE_VERSION;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Error {
CallbackError,
CorruptFile,
CouldNotAttach,
CouldNotMapFile,
CouldNotOpenFile,
InsufficientMemory,
InternalFatalError,
InvalidFile,
ScanTimeout,
SyntaxError,
TooManyMatches,
UnsupportedFileVersion,
Unknown(i32),
}
impl Error {
pub fn from_code(code: c_int) -> Result<(), Error> {
use self::Error::*;
if code as u32 == ERROR_SUCCESS {
return Ok(());
}
Err(match code as u32 {
ERROR_CALLBACK_ERROR => CallbackError,
ERROR_CORRUPT_FILE => CorruptFile,
ERROR_COULD_NOT_ATTACH_TO_PROCESS => CouldNotAttach,
ERROR_COULD_NOT_MAP_FILE => CouldNotMapFile,
ERROR_COULD_NOT_OPEN_FILE => CouldNotOpenFile,
ERROR_INSUFFICIENT_MEMORY => InsufficientMemory,
ERROR_INTERNAL_FATAL_ERROR => InternalFatalError,
ERROR_INVALID_FILE => InvalidFile,
ERROR_SCAN_TIMEOUT => ScanTimeout,
ERROR_SYNTAX_ERROR => SyntaxError,
ERROR_TOO_MANY_MATCHES => TooManyMatches,
ERROR_UNSUPPORTED_FILE_VERSION => UnsupportedFileVersion,
_ => Unknown(code),
})
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.clone().into())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
self.clone().into()
}
}
impl From<Error> for &'static str {
fn from(error: Error) -> &'static str {
use self::Error::*;
match error {
CallbackError => "Callback returned an error",
CorruptFile => "Rule file is corrupt",
CouldNotAttach => "Could not attach to process",
CouldNotMapFile => "File could not be mapped into memory",
CouldNotOpenFile => "File could not be opened",
InsufficientMemory => "Insufficient memory to complete the operation",
InternalFatalError => "Internal fatal error",
InvalidFile => "File is not a valid rules file",
ScanTimeout => "Timeouted during scan",
SyntaxError => "Syntax error in rule",
TooManyMatches => "Too many matches",
UnsupportedFileVersion => "Rule file version is not supported",
Unknown(_) => "Unknown Yara error",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_from_code() {
use super::Error::*;
assert_eq!(Ok(()), Error::from_code(ERROR_SUCCESS as i32));
assert_eq!(
Err(InsufficientMemory),
Error::from_code(ERROR_INSUFFICIENT_MEMORY as i32)
);
assert_eq!(
Err(ScanTimeout),
Error::from_code(ERROR_SCAN_TIMEOUT as i32)
);
}
#[test]
fn test_to_string() {
use std::error::Error as StdError;
assert_eq!(
"Callback returned an error",
Error::CallbackError.to_string()
);
assert_eq!(
"Callback returned an error",
Error::CallbackError.description()
);
}
}