yara_x/lib.rs
1/*! A YARA compiler and scanner completely written in Rust from scratch.
2
3It is 99% compatible with existing YARA rules and intends to be a safer, more
4efficient implementation of YARA.
5
6There are two main types in this crate: [`Compiler`] and [`Scanner`]. A compiler
7takes YARA source code and produces compiled [`Rules`] that are passed to the
8scanner for scanning files or in-memory data. The [`Rules`] produced by the
9compiler can be safely passed to multiple instances of [`Scanner`], but each
10instance of the scanner can be used for scanning a single file or memory buffer
11at a time. The scanner can be re-used for scanning multiple files or memory-buffers,
12though.
13
14# Example
15
16```rust
17# use yara_x;
18// Create a compiler.
19let mut compiler = yara_x::Compiler::new();
20
21// Add some YARA source code to compile.
22compiler.add_source(r#"
23 rule lorem_ipsum {
24 strings:
25 $ = "Lorem ipsum"
26 condition:
27 all of them
28 }
29"#).unwrap();
30
31// Obtain the compiled YARA rules.
32let rules = compiler.build();
33
34// Create a scanner that uses the compiled rules.
35let mut scanner = yara_x::Scanner::new(&rules);
36
37// Scan some data.
38let results = scanner.scan("Lorem ipsum".as_bytes()).unwrap();
39
40assert_eq!(results.matching_rules().len(), 1);
41```
42*/
43
44#![deny(missing_docs)]
45#![cfg_attr(docsrs, feature(doc_cfg))]
46extern crate core;
47
48pub use compiler::compile;
49pub use compiler::Compiler;
50pub use compiler::Patch;
51pub use compiler::Rules;
52pub use compiler::RulesIter;
53pub use compiler::SourceCode;
54pub use models::Match;
55pub use models::Matches;
56pub use models::MetaValue;
57pub use models::Metadata;
58pub use models::Pattern;
59pub use models::PatternKind;
60pub use models::Patterns;
61pub use models::Rule;
62pub use modules::mods;
63pub use scanner::blocks;
64pub use scanner::MatchingRules;
65pub use scanner::ModuleOutputs;
66pub use scanner::NonMatchingRules;
67#[cfg(feature = "rules-profiling")]
68pub use scanner::ProfilingData;
69pub use scanner::ScanError;
70pub use scanner::ScanOptions;
71pub use scanner::ScanResults;
72pub use scanner::Scanner;
73pub use variables::Variable;
74
75mod compiler;
76mod modules;
77mod re;
78mod scanner;
79mod string_pool;
80mod symbols;
81mod types;
82mod variables;
83mod wasm;
84
85mod models;
86#[cfg(test)]
87mod tests;
88
89/// Current version number as a string (example: "1.9.0").
90pub const VERSION: &str = env!("CARGO_PKG_VERSION");
91
92pub mod linters {
93 //! Linters that can be added to the compiler for performing additional checks.
94 //!
95 //! This module contains the linters that can be passed to [`crate::Compiler::add_linter`]
96 //! for performing additional checks to the YARA rules being compiled.
97 pub use crate::compiler::linters::*;
98}
99
100pub mod errors {
101 //! Errors returned by this crate.
102 //!
103 //! This module contains the definitions for all error types returned by this
104 //! crate.
105 pub use crate::compiler::errors::*;
106 pub use crate::modules::ModuleError;
107 pub use crate::scanner::ScanError;
108 pub use crate::variables::VariableError;
109}
110
111pub mod warnings {
112 //! Warnings returned while compiling rules.
113 pub use crate::compiler::warnings::*;
114}
115
116mod utils {
117 /// Tries to match `target` as the enum variant `pat`. Returns the
118 /// inner value contained in the variant, or panics if `target` does
119 /// not match `pat`.
120 ///
121 /// For example...
122 ///
123 /// ```ignore
124 /// cast!(target, pat)
125 /// ```
126 ///
127 /// expands to...
128 ///
129 /// ```ignore
130 /// if let pat(inner) = target {
131 /// inner
132 /// } else {
133 /// panic!("mismatch variant when cast to {}", stringify!($pat));
134 /// }
135 /// ```
136 macro_rules! cast {
137 ($target: expr, $pat: path) => {{
138 if let $pat(inner) = $target {
139 inner
140 } else {
141 panic!("mismatch variant when cast to {}", stringify!($pat));
142 }
143 }};
144 }
145
146 pub(crate) use cast;
147}
148
149/// Finalizes YARA-X.
150///
151/// This function only needs to be called in a very specific scenario:
152/// when YARA-X is used as a dynamically loaded library (`.so`, `.dll`,
153/// `.dylib`) **and** that library must be unloaded at runtime.
154///
155/// Its primary purpose is to remove the process-wide signal handlers
156/// installed by the [wasmtime] engine.
157///
158/// # Safety
159///
160/// This function is **unsafe** to call under normal circumstances. It has
161/// strict preconditions that must be met:
162///
163/// - There must be no other active `wasmtime` engines in the process. This
164/// applies not only to clones of the engine used by YARA-X (which should not
165/// exist because YARA-X uses a single copy of its engine), but to *any*
166/// `wasmtime` engine, since global state shared by all engines is torn
167/// down.
168///
169/// - On Unix platforms, no other signal handlers may have been installed
170/// for signals intercepted by `wasmtime`. If other handlers have been set,
171/// `wasmtime` cannot reliably restore the original state, which may lead
172/// to undefined behavior.
173///
174/// [wasmtime]: https://wasmtime.dev/
175pub unsafe fn finalize() {
176 wasm::free_engine();
177}