diff --git a/Cargo.toml b/Cargo.toml index b0ee54a92..34dec3f0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ members = [ "py", "ls", ] +exclude = ["examples/custom-module"] resolver = "3" diff --git a/docs/ModuleDeveloperGuide.md b/docs/ModuleDeveloperGuide.md index b0175bf63..45ce0279b 100644 --- a/docs/ModuleDeveloperGuide.md +++ b/docs/ModuleDeveloperGuide.md @@ -25,6 +25,13 @@ words - [Adding dependencies](#adding-dependencies) - [Using enums](#using-enums) - [Inline enums](#inline-enums) +- [Creating a module in an external crate](#creating-a-module-in-an-external-crate) + - [Setting up the crate](#setting-up-the-crate) + - [Compiling the proto at build time](#compiling-the-proto-at-build-time) + - [Registering the module](#registering-the-module) + - [Adding callable functions to an external module](#adding-callable-functions-to-an-external-module) + - [Overriding the module output at scan time](#overriding-the-module-output-at-scan-time) + - [Ensuring the module is linked](#ensuring-the-module-is-linked) - [Tests](#tests) - [Structuring Testdata Input](#structuring-testdata-input) - [Linux](#linux) @@ -121,7 +128,6 @@ Let's start with the interesting part: option (yara.module_options) = { name : "text" root_message: "text.Text" - rust_module: "text" cargo_feature: "text-module" }; ``` @@ -133,10 +139,10 @@ file, but one describing a module. In fact, you can put any `.proto` file in the files is describing a YARA module. Only files containing a `yara.module_options` section will define a module. -Options `name` and `root_message` are required, while `rust_module` and -`cargo_feature` are optional. The `name` option defines the module's name. This -is the name that will be used for importing the module in a YARA rule, in this -case our module will be imported with `import "text"`. +Options `name` and `root_message` are required, while `cargo_feature` is optional. +The `name` option defines the module's name. This is the name that will be used +for importing the module in a YARA rule, in this case our module will be imported +with `import "text"`. The `cargo_feature` option indicates the name of the feature that controls whether @@ -292,11 +298,6 @@ need write the logic that parses every scanned file and fills the module's structure with the data obtained from the file. This is done by implementing a function that will act as the entry point for your module. -This is where the `rust_module` option described in the previous section enters -into play. This option is the name of the Rust module that contains the code -for your module. In our `text.proto` file we have `rust_module: "text"`, which -means that our Rust module must be named `text`. - There are two options for creating our `text` module: * Creating a `text.rs` file in `lib/src/modules`. @@ -309,24 +310,25 @@ second approach is the recommended one. So, let's create our `lib/src/modules/text.rs` file: ```rust -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::text::*; -#[module_main] -fn main(data: &[u8]) -> Text { +fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { let mut text_proto = Text::new(); // TODO: parse the data and populate text_proto. - text_proto + Ok(text_proto) } + +register_module!("text", Text, main); ``` This is the simplest possible code for a YARA module, and it doesn't do anything special yet. Let's describe what it does in detail: ```rust -use crate::modules::prelude::*; +use crate::mods::prelude::*; ``` This first line is very important as it imports all the dependencies required @@ -348,38 +350,36 @@ will be `crate::modules::protos::foobar` --- -Next comes the module's main function: +Next comes the module's main function and the module registration: ```rust -#[module_main] -fn main(data: &[u8]) -> Text { +fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { ... } + +register_module!("text", Text, main); ``` The module's main function is called for every file scanned by YARA. This -function receives a byte slice with the content of the file being scanned. It -must return the `Text` structure that was generated from the `text.proto` file. -The main function must have the `#[module_main]` attribute. Notice that the -module's main function doesn't need to be called `main`, it can have any -arbitrary name, as long as it has the `#[module_main]` attribute. Of course, -this attribute can't be used with more than one function per module. - -The main function usually consists in creating an instance of the protobuf -you previously defined, and populating the protobuf with information extracted -from -the scanned file. Let's finish the implementation of the main function for our -`text` module. +function receives a byte slice with the content of the file being scanned and an +optional byte slice with per-scan metadata, and it returns a `Result` containing the +`Text` structure that was generated from the `text.proto` file (or a `ModuleError`). + +Registering the module is as simple as calling the `register_module!` macro. +It takes the name of the module (as used in YARA rules' `import` statements), the +protobuf message type returned by the module, and the main function name. If the +module is a data-only module with no main function, the third argument can be omitted. + +Let's finish the implementation of the main function for our `text` module. ```rust -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::text::*; use std::io; use std::io::BufRead; -#[module_main] -fn main(data: &[u8]) -> Text { +fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { // Create an empty instance of the Text protobuf. let mut text_proto = Text::new(); @@ -396,7 +396,7 @@ fn main(data: &[u8]) -> Text { num_words += line.split_whitespace().count(); num_lines += 1; } - Err(_) => return text_proto, + Err(_) => return Ok(text_proto), } } @@ -405,8 +405,10 @@ fn main(data: &[u8]) -> Text { text_proto.set_num_words(num_words as i64); // Return the Text proto after filling the relevant fields. - text_proto + Ok(text_proto) } + +register_module!("text", Text, main); ``` That's all you need for having a fully functional YARA module. Now, let's build @@ -1009,6 +1011,202 @@ enum CPU_SUBTYPE_ARM { With the enums above you can refer to `macho.CPU_TYPE_X86` and instead of `macho.CPU_TYPE.CPU_TYPE_X86` and `macho.CPU_SUBTYPE_INTEL.CPU_SUBTYPE_I386`. +## Creating a module in an external crate + +Everything described so far assumes that your module lives inside the +`yara-x` repository itself. This is the right approach when you intend to +contribute the module upstream, but it requires modifying the `yara-x` source +tree and rebuilding the library. If you want to ship a module as part of your +own crate—without forking or patching `yara-x`—you can use the **custom +modules** API instead. + +Custom modules are registered at link time through the +[inventory](https://docs.rs/inventory) crate. When your crate is linked into +a binary together with `yara-x`, the module is discovered automatically and +behaves exactly like a built-in module: it can be `import`-ed in rules, its +fields are accessible in conditions, and its functions are callable. + +### Setting up the crate + +Add `yara-x` and `protobuf` as dependencies: + +```toml +[dependencies] +yara-x = { version = "..." } +protobuf = { version = "3" } + +[build-dependencies] +protobuf-codegen = { version = "3" } +``` + +### Compiling the proto at build time + +Just like built-in modules, an external module's structure is described by a +`.proto` file. The difference is that instead of placing it inside the +`yara-x` source tree and relying on `yara-x`'s own build script, you compile +it yourself in `build.rs` using `protobuf-codegen`: + +```protobuf +// proto/foobar.proto +syntax = "proto2"; + +package foobar; + +message Foobar { + optional uint64 count = 1; + optional string label = 2; + repeated string tags = 3; +} +``` + +```rust +// build.rs +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=proto"); + + protobuf_codegen::Codegen::new() + .pure() + .cargo_out_dir("protos") + .include("proto") + .input("proto/foobar.proto") + .run_from_script(); +} +``` + +The `.pure()` call tells `protobuf-codegen` to use its built-in Rust parser, +so you do not need to have `protoc` installed. The generated code is placed +under `$OUT_DIR/protos/`, and you include it from your library like this: + +```rust +pub mod proto { + include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); +} +pub use proto::foobar::Foobar; +``` + +### Registering the module + +With the proto in place, registering the module requires two things: a main +function and a call to `yara_x::register_module!`. The main function follows the same +contract as in built-in modules—it receives the scanned data, populates the +protobuf, and returns it: + +```rust +use yara_x::errors::ModuleError; + +fn foobar_main( + data: &[u8], + _meta: Option<&[u8]>, +) -> Result { + let mut out = Foobar::new(); + out.count = Some(data.len() as u64); + out.label = Some("foobar".to_owned()); + Ok(out) +} + +yara_x::register_module!("foobar", Foobar, foobar_main); +``` + +A few things to note here: + +* The first argument is the string used in `import "foobar"` in YARA rules. +* The second argument is the root protobuf message type. The root descriptor is automatically obtained from this type. +* The third argument is the main function. If your module is data-only (the caller always + injects the output via `set_module_output`), it can be omitted. +* The macro automatically sets the Rust module name path via `module_path!()` so that YARA can find any callable functions. + +If a custom module shares its name with a built-in module, the built-in one +takes precedence and your registration is silently ignored. + +### Adding callable functions to an external module + +Custom modules can also export functions that are callable from YARA rules, the +same way built-in modules do with `#[module_export]`. From an external crate +you use the same attribute, but you must pass an extra `yara_x_crate` +argument so that the macro can generate fully-qualified type references: + +```rust +pub mod fns { + use yara_x::ScanContext; + + #[yara_x::module_export(yara_x_crate = "yara_x")] + pub fn add(_ctx: &ScanContext, a: i64, b: i64) -> i64 { + a + b + } +} +``` + +The `yara_x_crate = "yara_x"` argument is required whenever the macro is used +outside of the `yara-x` source tree. Without it the macro generates bare type +names (`Caller`, `ScanContext`, etc.) that are only in scope inside `yara-x`. + +The function signature rules are exactly the same as for built-in modules— +see [Valid function arguments](#valid-function-arguments) and +[Valid return types](#valid-return-types). + +After this, the `add` function is callable from YARA rules as `foobar.add(a, b)`: + +```yara +import "foobar" + +rule add_works { + condition: + foobar.add(3, 4) == 7 +} +``` + +### Overriding the module output at scan time + +Sometimes you already have the data your module would expose, and you don't +want to re-derive it inside `main_fn`. The `Scanner` API lets you inject a +pre-built protobuf directly, bypassing `main_fn` entirely for that scan: + +```rust +let rules = yara_x::Compiler::new() + .add_source(r#"import "foobar" rule r { condition: foobar.count == 99 }"#)? + .build(); + +let mut out = Foobar::new(); +out.count = Some(99); + +let mut scanner = yara_x::Scanner::new(&rules); +scanner.set_module_output(Box::new(out))?; +scanner.scan(data)?; +``` + +`set_module_output` identifies the target module by the type of the message +you pass in. YARA matches it against the `root_descriptor` you registered, so +the type must be exactly the message type declared as your module's root. + +### Ensuring the module is linked + +Rust's linker may discard your crate's `inventory::submit!` initializer if +nothing in the final binary directly references a symbol from your crate. +The safest workaround is to expose a no-op function and call it from the +binary's entry point: + +```rust +/// Call this from your binary's `main` (or from test setup) to ensure +/// the linker keeps this crate's module registration. +pub fn ensure_registered() {} +``` + +```rust +fn main() { + my_module_crate::ensure_registered(); + // ... +} +``` + +You can verify that the registration worked by checking the module registry: + +```rust +my_module_crate::ensure_registered(); +let names: Vec<&str> = yara_x::mods::module_names().collect(); +assert!(names.contains(&"foobar")); +``` + ## Tests You'll notice that each module in `/lib/src/modules/` has a `tests/` diff --git a/examples/custom-module/Cargo.lock b/examples/custom-module/Cargo.lock new file mode 100644 index 000000000..3d54358c4 --- /dev/null +++ b/examples/custom-module/Cargo.lock @@ -0,0 +1,2798 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" +dependencies = [ + "gimli 0.33.0", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "annotate-snippets" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" +dependencies = [ + "anstyle", + "memchr", + "unicode-width", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "ascii_tree" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6c635b3aa665c649ad1415f1573c85957dfa47690ec27aebe7ec17efe3c643" + +[[package]] +name = "asn1-rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom 7.1.3", + "num-traits", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "bincode_derive", + "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "cc" +version = "1.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "countme" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-assembler-x64" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc822414b18d1f5b1b33ce1441534e311e62fef86ebb5b9d382af857d0272c9" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c646808b06f4532478d8d6057d74f15c3322f10d995d9486e7dcea405bf521a" +dependencies = [ + "cranelift-srcgen", +] + +[[package]] +name = "cranelift-bforest" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5996f01a686b2349cdb379083ec5ad3e8cb8767fb2d495d3a4f2ee4163a18d" +dependencies = [ + "cranelift-entity", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-bitset" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523fea83273f6a985520f57788809a4de2165794d9ab00fb1254fceb4f5aa00c" +dependencies = [ + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d73d1e372730b5f64ed1a2bd9f01fe4686c8ec14a28034e3084e530c8d951878" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli 0.33.0", + "hashbrown 0.16.1", + "libm", + "log", + "pulley-interpreter", + "regalloc2", + "rustc-hash 2.1.2", + "serde", + "smallvec", + "target-lexicon", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0319c18165e93dc1ebf78946a8da0b1c341c95b4a39729a69574671639bdb5f" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck", + "pulley-interpreter", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9195cd8aeecb55e401aa96b2eaa55921636e8246c127ed7908f7ef7e0d40f270" + +[[package]] +name = "cranelift-control" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8976c2154b74136322befc74222ab5c7249edd7e2604f8cbef2b94975541ffb9" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6038b3147c7982f4951150d5f96c7c06c1e7214b99d4b4a98607aadf8ded89d1" +dependencies = [ + "cranelift-bitset", + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-frontend" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbd294abe236e23cc3d907b0936226b6a8342db7636daa9c7c72be1e323420e" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a90b6ed3aba84189352a87badeb93b2126d3724225a42dc67fdce53d1b139c" + +[[package]] +name = "cranelift-native" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ec0cc1a54e22925eacf4fc3dc815f907734d3b377899d19d52bec04863e853" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-srcgen" +version = "0.130.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "948865622f87f30907bb46fbb081b235ae63c1896a99a83c26a003305c1fa82d" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "custom-module" +version = "0.0.0" +dependencies = [ + "protobuf", + "protobuf-codegen", + "yara-x", +] + +[[package]] +name = "daachorse" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d87f75bbe32ee10609201e09e818537df81c3acb436be2b78f47cc85d139475" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom 7.1.3", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dsa" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" +dependencies = [ + "digest", + "num-bigint-dig", + "num-traits", + "pkcs8", + "rfc6979", + "sha2", + "signature", + "zeroize", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "miniz_oxide", + "zlib-rs", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" +dependencies = [ + "fnv", + "hashbrown 0.16.1", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "intaglio" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e062125b1cb1523e2032c12f3a5bac6947ccd1f8c0a8aae96f63609fe0e34ee" + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cc46bac87ef8093eed6f272babb833b6443374399985ac8ed28471ee0918545" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "logos" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "rustc_version", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "md2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4f0f3ed25ff4f8d8d102288d92f900efc202661c884cf67dfe4f0d07c43d1f" +dependencies = [ + "digest", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix 1.1.4", +] + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" +dependencies = [ + "crc32fast", + "hashbrown 0.16.1", + "indexmap", + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protobuf" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-codegen" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3976825c0014bbd2f3b34f0001876604fe87e0c86cd8fa54251530f1544ace" +dependencies = [ + "anyhow", + "once_cell", + "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-parse" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4aeaa1f2460f1d348eeaeed86aea999ce98c1bded6f089ff8514c9d9dbdc973" +dependencies = [ + "anyhow", + "indexmap", + "log", + "protobuf", + "protobuf-support", + "tempfile", + "thiserror 1.0.69", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "psl" +version = "2.1.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bde51f827dca976f8f9a8c91329a3193114dc076b8012a1ee3624f1588c3582" +dependencies = [ + "psl-types", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "pulley-interpreter" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ec12fe19a9588315a49fe5704502a9c02d6a198303314b0c7c86123b06d29e5" +dependencies = [ + "cranelift-bitset", + "log", + "pulley-macros", + "wasmtime-internal-core", +] + +[[package]] +name = "pulley-macros" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f7d5ef31ebf1b46cd7e722ffef934e670d7e462f49aa01cde07b9b76dca580" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "regalloc2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de2c52737737f8609e94f975dee22854a2d5c125772d4b1cf292120f4d45c186" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.17.1", + "log", + "rustc-hash 2.1.2", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rowan" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21" +dependencies = [ + "countme", + "hashbrown 0.14.5", + "rustc-hash 1.1.0", + "text-size", +] + +[[package]] +name = "roxmltree" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb" +dependencies = [ + "memchr", +] + +[[package]] +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "text-size" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "walrus" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e151599d689dac80e85c66a7cfa6ffd1b2ab79220517f9161040a87a5041aee3" +dependencies = [ + "anyhow", + "gimli 0.32.3", + "id-arena", + "leb128", + "log", + "walrus-macro", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", +] + +[[package]] +name = "walrus-macro" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9b0525d7ea6e5f906aca581a172e5c91b4c595290dfa8ad4a2bc9ffef33b44" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" +dependencies = [ + "leb128fmt", + "wasmparser 0.245.1", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" +dependencies = [ + "bitflags", + "hashbrown 0.16.1", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wasmprinter" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41517a3716fbb8ccf46daa9c1325f760fcbff5168e75c7392288e410b91ac8" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.245.1", +] + +[[package]] +name = "wasmtime" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb1ed5899dde98357cfdcf647a4614498798719793898245b4b34e663addabf" +dependencies = [ + "addr2line", + "async-trait", + "bitflags", + "bumpalo", + "cc", + "cfg-if", + "libc", + "log", + "mach2", + "memfd", + "object", + "once_cell", + "postcard", + "pulley-interpreter", + "rustix 1.1.4", + "serde", + "serde_derive", + "smallvec", + "target-lexicon", + "wasmparser 0.245.1", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-cranelift", + "wasmtime-internal-fiber", + "wasmtime-internal-jit-debug", + "wasmtime-internal-jit-icache-coherence", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-environ" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4172382dcc785c31d0e862c6780a18f5dd437914d22c4691351f965ef751c821" +dependencies = [ + "anyhow", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-entity", + "gimli 0.33.0", + "hashbrown 0.16.1", + "indexmap", + "log", + "object", + "postcard", + "serde", + "serde_derive", + "sha2", + "smallvec", + "target-lexicon", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", + "wasmprinter", + "wasmtime-internal-core", +] + +[[package]] +name = "wasmtime-internal-core" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3820b174f477d2a7083209d1ad5353fcdb11eaea434b2137b8681029460dd3" +dependencies = [ + "hashbrown 0.16.1", + "libm", + "serde", +] + +[[package]] +name = "wasmtime-internal-cranelift" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1679d205caf9766c6aa309d45bb3e7c634d7725e3164404df33824b9f7c4fb7" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "gimli 0.33.0", + "itertools", + "log", + "object", + "pulley-interpreter", + "smallvec", + "target-lexicon", + "thiserror 2.0.18", + "wasmparser 0.245.1", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-fiber" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e505254058be5b0df458d670ee42d9eafe2349d04c1296e9dc01071dc20a85" +dependencies = [ + "cc", + "cfg-if", + "libc", + "rustix 1.1.4", + "wasmtime-environ", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-jit-debug" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c2e05b345f1773e59c20e6ad7298fd6857cdea245023d88bb659c96d8f0ea72" +dependencies = [ + "cc", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-jit-icache-coherence" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b86701b234a4643e3f111869aa792b3a05a06e02d486ee9cb6c04dae16b52dab" +dependencies = [ + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-unwinder" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63558d801beb83dde9b336eb4ae049019aee26627926edb32cd119d7e4c83cd" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "log", + "object", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-internal-versioned-export-macros" +version = "43.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "737c4d956fc3a848541a064afb683dd2771132a6b125be5baaf95c4379aa47df" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.244.0", + "wasm-metadata", + "wasmparser 0.244.0", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.244.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "yara-x" +version = "1.16.0" +dependencies = [ + "annotate-snippets", + "anyhow", + "base64", + "bincode", + "bitflags", + "bitvec", + "bstr", + "const-oid", + "crc32fast", + "daachorse", + "der-parser", + "digest", + "dsa", + "ecdsa", + "getrandom 0.2.17", + "globwalk", + "hex", + "indexmap", + "intaglio", + "inventory", + "ipnet", + "itertools", + "js-sys", + "md-5", + "md2", + "memchr", + "memmap2", + "nom 8.0.0", + "num-derive", + "num-traits", + "p256", + "p384", + "protobuf", + "protobuf-codegen", + "protobuf-parse", + "psl", + "regex", + "regex-automata", + "regex-syntax", + "roxmltree", + "rsa", + "rustc-hash 2.1.2", + "serde", + "serde_json", + "sha1", + "sha2", + "simd-adler32", + "simd_cesu8", + "smallvec", + "strum_macros", + "thiserror 2.0.18", + "uuid", + "walrus", + "wasm-bindgen", + "wasmtime", + "x509-parser", + "yara-x-macros", + "yara-x-parser", + "yara-x-proto", + "zip", +] + +[[package]] +name = "yara-x-macros" +version = "1.16.0" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "yara-x-parser" +version = "1.16.0" +dependencies = [ + "ascii_tree", + "bitflags", + "bstr", + "indexmap", + "itertools", + "logos", + "num-traits", + "rowan", + "rustc-hash 2.1.2", + "serde", +] + +[[package]] +name = "yara-x-proto" +version = "1.16.0" +dependencies = [ + "protobuf", + "protobuf-codegen", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zip" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" +dependencies = [ + "crc32fast", + "flate2", + "indexmap", + "memchr", + "typed-path", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] diff --git a/examples/custom-module/Cargo.toml b/examples/custom-module/Cargo.toml new file mode 100644 index 000000000..b499c0b75 --- /dev/null +++ b/examples/custom-module/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "custom-module" +description = """ +Example crate demonstrating how to register a custom YARA-X module from an +external crate. +""" +edition = "2024" +publish = false + +[lib] +# A regular Rust library. The `register_module!` invocation in `src/lib.rs` +# registers the custom module at link time. +path = "src/lib.rs" + +[dependencies] +# `yara-x` is consumed via the workspace path so this example always builds +# against the in-tree version. +yara-x = { path = "../../lib" } +# The `protobuf` crate is needed because the registered main function returns +# a protobuf. +protobuf = "3.7.2" + +[build-dependencies] +# Compiles `proto/custom_test.proto` into Rust code at build time. The +# `pure` mode is selected so that no external `protoc` binary is required. +protobuf-codegen = "3.7.2" diff --git a/examples/custom-module/build.rs b/examples/custom-module/build.rs new file mode 100644 index 000000000..31d75dfc9 --- /dev/null +++ b/examples/custom-module/build.rs @@ -0,0 +1,11 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=proto"); + + protobuf_codegen::Codegen::new() + .pure() + .cargo_out_dir("protos") + .include("proto") + .input("proto/foobar.proto") + .run_from_script(); +} diff --git a/examples/custom-module/proto/foobar.proto b/examples/custom-module/proto/foobar.proto new file mode 100644 index 000000000..8232aac2b --- /dev/null +++ b/examples/custom-module/proto/foobar.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +package foobar; + +message Foobar { + optional uint64 count = 1; + optional string label = 2; + repeated string tags = 3; +} diff --git a/examples/custom-module/src/lib.rs b/examples/custom-module/src/lib.rs new file mode 100644 index 000000000..96cb211fc --- /dev/null +++ b/examples/custom-module/src/lib.rs @@ -0,0 +1,37 @@ +//! Example of registering a custom YARA-X module from an external crate. +//! +//! The `foobar` module defined here is registered at link time via +//! [`inventory::submit!`]. Any binary that links against this crate can then +//! use `import "foobar"` in YARA rules and read `foobar.count`, `foobar.label`, +//! `foobar.tags`, and call `foobar.add(a, b)`. +//! +//! The module's main function populates the protobuf from the scanned data. +//! Callers can also override the output for a specific scan by calling +//! [`yara_x::Scanner::set_module_output`] before [`yara_x::Scanner::scan`]. + +use yara_x::errors::ModuleError; +use yara_x::mods::prelude::*; + +pub mod proto { + include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); +} + +pub use proto::foobar::Foobar; + +fn foobar_main( + data: &[u8], + _meta: Option<&[u8]>, +) -> Result { + let mut out = Foobar::new(); + out.count = Some(data.len() as u64); + out.label = Some("foobar".to_owned()); + Ok(out) +} + +/// Returns the sum of two integers. Callable from rules as `foobar.add(a, b)`. +#[module_export] +pub fn add(_ctx: &ScanContext, a: i64, b: i64) -> i64 { + a + b +} + +register_module!("foobar", Foobar, foobar_main); diff --git a/examples/custom-module/tests/integration.rs b/examples/custom-module/tests/integration.rs new file mode 100644 index 000000000..6f0cc93b0 --- /dev/null +++ b/examples/custom-module/tests/integration.rs @@ -0,0 +1,122 @@ +use custom_module::Foobar; + +fn compile(src: &str) -> yara_x::Rules { + let mut c = yara_x::Compiler::new(); + c.add_source(src).expect("rules must compile"); + c.build() +} + +fn matches(rules: &yara_x::Rules, data: &[u8]) -> Vec { + yara_x::Scanner::new(rules) + .scan(data) + .unwrap() + .matching_rules() + .map(|r| r.identifier().to_owned()) + .collect() +} + +fn matches_with_output( + rules: &yara_x::Rules, + data: &[u8], + output: Foobar, +) -> Vec { + let mut scanner = yara_x::Scanner::new(rules); + scanner.set_module_output(Box::new(output)).unwrap(); + scanner + .scan(data) + .unwrap() + .matching_rules() + .map(|r| r.identifier().to_owned()) + .collect() +} + +// --------------------------------------------------------------------------- + +#[test] +fn module_is_in_registry() { + let names: Vec<&str> = yara_x::mods::module_names().collect(); + assert!(names.contains(&"foobar"), "foobar not in {names:?}"); +} + +#[test] +fn main_fn_populates_count_and_label() { + let rules = compile( + r#" + import "foobar" + rule count_matches { condition: foobar.count == 4 } + rule label_matches { condition: foobar.label == "foobar" } + "#, + ); + let matched = matches(&rules, b"data"); + assert!(matched.contains(&"count_matches".to_owned())); + assert!(matched.contains(&"label_matches".to_owned())); +} + +#[test] +fn set_module_output_overrides_main_fn() { + let rules = compile( + r#" + import "foobar" + rule has_tag_alpha { condition: for any t in foobar.tags : (t == "alpha") } + rule count_is_99 { condition: foobar.count == 99 } + "#, + ); + + let mut output = Foobar::new(); + output.count = Some(99); + output.label = Some("custom".to_owned()); + output.tags = vec!["alpha".to_owned(), "beta".to_owned()]; + + let matched = matches_with_output(&rules, b"ignored", output); + assert!(matched.contains(&"has_tag_alpha".to_owned())); + assert!(matched.contains(&"count_is_99".to_owned())); +} + +#[test] +fn compiled_rules_survive_serialize_deserialize() { + let rules = compile( + r#" + import "foobar" + rule label_check { condition: foobar.label == "persisted" } + "#, + ); + + let blob = rules.serialize().expect("serialization must succeed"); + let rules = yara_x::Rules::deserialize(blob) + .expect("deserialization must succeed"); + + let mut output = Foobar::new(); + output.label = Some("persisted".to_owned()); + + let matched = matches_with_output(&rules, b"", output); + assert_eq!(matched, vec!["label_check"]); +} + +#[test] +fn module_fn_add_works() { + let rules = compile( + r#" + import "foobar" + rule add_works { condition: foobar.add(3, 4) == 7 } + "#, + ); + let matched = matches(&rules, b"data"); + assert!(matched.contains(&"add_works".to_owned())); +} + +#[test] +fn no_tags_rule_does_not_match_when_tags_present() { + let rules = compile( + r#" + import "foobar" + rule no_tags { condition: foobar.count == 0 and not (for any t in foobar.tags : (true)) } + "#, + ); + + let mut output = Foobar::new(); + output.count = Some(0); + output.tags = vec!["something".to_owned()]; + + let matched = matches_with_output(&rules, b"", output); + assert!(matched.is_empty()); +} diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 583fdccd5..7a7c5fa9c 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -66,8 +66,6 @@ generate-proto-code = [ # This feature is disabled by default. generate-module-docs = ["protoc"] - - # Whether to use protoc for parsing and compiling .proto files. By default, # .proto files are parsed and compiled by the pure-Rust compiler implemented # by the `protobuf_codegen` crate. With this feature you can change this @@ -76,8 +74,6 @@ generate-module-docs = ["protoc"] # plugin. Follow the instructions in: https://lib.rs/crates/protobuf-codegen3 protoc = [] - - # Enables debug logs. logging = ["dep:log", "dep:quanta"] diff --git a/lib/build.rs b/lib/build.rs index 365db3776..bee9b4dd3 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -6,7 +6,6 @@ use protobuf::descriptor::FileDescriptorProto; struct Module { name: String, proto_mod: String, - rust_mod: Option, cargo_feature: Option, root_msg: String, } @@ -18,7 +17,6 @@ fn generate_module_files(proto_files: &[FileDescriptorProto]) -> Vec { use std::path::PathBuf; use yara_x_proto::exts::module_options as yara_module_options; - println!("cargo:rerun-if-changed=src/modules/add_modules.rs"); println!("cargo:rerun-if-changed=src/modules/modules.rs"); let mut modules = Vec::new(); @@ -50,7 +48,6 @@ fn generate_module_files(proto_files: &[FileDescriptorProto]) -> Vec { modules.push(Module { name: module_options.name.unwrap(), proto_mod: proto_name, - rust_mod: module_options.rust_module, cargo_feature: module_options.cargo_feature, root_msg, }); @@ -87,23 +84,6 @@ fn generate_module_files(proto_files: &[FileDescriptorProto]) -> Vec { ) .unwrap(); - // Create the add_modules.rs files, with an entry for each proto that - // defines a YARA module. Each entry looks like: - // - // #[cfg(feature = "foo_module")] - // add_module!(modules, "foo", foo, Some(foo::__main__ as MainFn)); - // - let mut add_modules_rs = - File::create("src/modules/add_modules.rs").unwrap(); - - writeln!( - add_modules_rs, - "// File generated automatically by build.rs. Do not edit." - ) - .unwrap(); - - write!(add_modules_rs, "{{").unwrap(); - // Sort modules by name, so that they always appear in the same order // no matter the platform. If modules are not sorted, the order will // vary from one platform to the other, in the same way that HashMap @@ -111,26 +91,8 @@ fn generate_module_files(proto_files: &[FileDescriptorProto]) -> Vec { modules.sort_by(|a, b| a.name.cmp(&b.name)); for m in &modules { - let name = &m.name; - let proto_mod = &m.proto_mod; - let rust_mod = &m.rust_mod; + let module_name = m.name.as_str(); let cargo_feature = &m.cargo_feature; - let root_message = &m.root_msg; - - // If the YARA module has an associated Rust module, this module must - // have a function named "main". If the YARA module doesn't have an - // associated YARA module, the main function is set to None. - let main_fn = if let Some(rust_mod) = &rust_mod { - format!("Some({rust_mod}::__main__ as MainFn)") - } else { - "None".to_string() - }; - - let rust_mod_name = if let Some(rust_mod) = &rust_mod { - format!(r#"Some("{rust_mod}")"#) - } else { - "None".to_string() - }; let cfg_feature = if let Some(cargo_feature) = &cargo_feature { format!(r#"#[cfg(feature = "{cargo_feature}")]"#) @@ -138,27 +100,15 @@ fn generate_module_files(proto_files: &[FileDescriptorProto]) -> Vec { "".to_string() }; - if let Some(rust_mod) = &rust_mod { - write!( - modules_rs, - r#" -{cfg_feature} -mod {rust_mod};"#, - ) - .unwrap(); - } - write!( - add_modules_rs, + modules_rs, r#" {cfg_feature} -add_module!(modules, "{name}", {proto_mod}, "{root_message}", {rust_mod_name}, {main_fn});"#, +mod {module_name};"#, ) - .unwrap(); + .unwrap(); } - write!(add_modules_rs, "\n}}").unwrap(); - modules } @@ -438,9 +388,8 @@ fn generate_proto_code() { // Generate .rs files for .proto files in src/modules/protos proto_compiler.run_from_script(); - // Decide whether `modules.rs`, `add_modules.rs` and the content of the - // `protos/generated` directory should be re-generated. By default, they - // will be re-generated. + // Decide whether `modules.rs` and the content of the `protos/generated` + // directory should be re-generated. By default, they will be re-generated. let mut regenerate = true; // If the environment variable `YRX_REGENERATE_MODULES_RS` is present, the diff --git a/lib/src/compiler/context.rs b/lib/src/compiler/context.rs index 5af13674c..05cd2752a 100644 --- a/lib/src/compiler/context.rs +++ b/lib/src/compiler/context.rs @@ -12,7 +12,6 @@ use crate::compiler::ir::{IR, PatternIdx}; use crate::compiler::report::ReportBuilder; use crate::compiler::{RegexId, RegexSetId, Warnings, ir}; use crate::errors::{UnknownField, UnknownIdentifier}; -use crate::modules::BUILTIN_MODULES; use crate::string_pool::StringPool; use crate::symbols::{StackedSymbolTable, Symbol, SymbolLookup}; use crate::types::Type; @@ -128,6 +127,8 @@ impl<'src> CompileContext<'_, 'src> { // If the current symbol table is `None` it means that the // identifier is not a field or method of some structure. return if symbol_table.is_none() { + let module = crate::modules::registered_modules() + .find(|module| module.name() == ident.name); // Build the error for the unknown identifier. let mut err = UnknownIdentifier::build( self.report_builder, @@ -135,18 +136,16 @@ impl<'src> CompileContext<'_, 'src> { self.report_builder.span_to_code_loc(ident.span()), // Add a note about the missing import statement if // the unknown identifier is a module name. - if BUILTIN_MODULES.contains_key(ident.name) { - Some(format!( + module.map(|m| { + format!( "there is a module named `{}`, but the `import \"{}\"` statement is missing", - ident.name, ident.name - )) - } else { - None - }, + m.name(), m.name()) + } + ) ); // If the identifier is a known module, add a fix that inserts // the import statement at the beginning of the file. - if BUILTIN_MODULES.contains_key(ident.name) { + if module.is_some() { err.report_mut().patch( self.report_builder.span_to_code_loc(Span(0..0)), format!("import \"{}\"\n", ident.name), diff --git a/lib/src/compiler/mod.rs b/lib/src/compiler/mod.rs index 099fd7861..97110a42c 100644 --- a/lib/src/compiler/mod.rs +++ b/lib/src/compiler/mod.rs @@ -38,7 +38,6 @@ use crate::compiler::errors::{ }; use crate::compiler::report::ReportBuilder; use crate::compiler::{CompileContext, VarStack}; -use crate::modules::BUILTIN_MODULES; use crate::re::hir::{ChainedPattern, ChainedPatternGap}; use crate::string_pool::{BStringPool, StringPool}; use crate::symbols::{StackedSymbolTable, Symbol, SymbolLookup, SymbolTable}; @@ -1851,7 +1850,8 @@ impl Compiler<'_> { fn c_import(&mut self, import: &Import) -> Result<(), CompileError> { let module_name = import.module_name; - let module = BUILTIN_MODULES.get(module_name); + let module = crate::modules::registered_modules() + .find(|m| m.name() == module_name); // Does a module with the given name actually exist? ... if module.is_none() { @@ -2627,7 +2627,7 @@ impl From for u32 { /// ID associated to each literal string in the literals pool. #[derive(PartialEq, Debug, Copy, Clone, Serialize, Deserialize)] #[serde(transparent)] -pub(crate) struct LiteralId(u32); +pub struct LiteralId(u32); impl From for LiteralId { fn from(v: i32) -> Self { diff --git a/lib/src/modules/add_modules.rs b/lib/src/modules/add_modules.rs deleted file mode 100644 index f85d24144..000000000 --- a/lib/src/modules/add_modules.rs +++ /dev/null @@ -1,37 +0,0 @@ -// File generated automatically by build.rs. Do not edit. -{ -#[cfg(feature = "console-module")] -add_module!(modules, "console", console, "console.Console", Some("console"), Some(console::__main__ as MainFn)); -#[cfg(feature = "crx-module")] -add_module!(modules, "crx", crx, "crx.Crx", Some("crx"), Some(crx::__main__ as MainFn)); -#[cfg(feature = "cuckoo-module")] -add_module!(modules, "cuckoo", cuckoo, "cuckoo.Cuckoo", Some("cuckoo"), Some(cuckoo::__main__ as MainFn)); -#[cfg(feature = "dex-module")] -add_module!(modules, "dex", dex, "dex.Dex", Some("dex"), Some(dex::__main__ as MainFn)); -#[cfg(feature = "dotnet-module")] -add_module!(modules, "dotnet", dotnet, "dotnet.Dotnet", Some("dotnet"), Some(dotnet::__main__ as MainFn)); -#[cfg(feature = "elf-module")] -add_module!(modules, "elf", elf, "elf.ELF", Some("elf"), Some(elf::__main__ as MainFn)); -#[cfg(feature = "hash-module")] -add_module!(modules, "hash", hash, "hash.Hash", Some("hash"), Some(hash::__main__ as MainFn)); -#[cfg(feature = "lnk-module")] -add_module!(modules, "lnk", lnk, "lnk.Lnk", Some("lnk"), Some(lnk::__main__ as MainFn)); -#[cfg(feature = "macho-module")] -add_module!(modules, "macho", macho, "macho.Macho", Some("macho"), Some(macho::__main__ as MainFn)); -#[cfg(feature = "magic-module")] -add_module!(modules, "magic", magic, "magic.Magic", Some("magic"), Some(magic::__main__ as MainFn)); -#[cfg(feature = "math-module")] -add_module!(modules, "math", math, "math.Math", Some("math"), Some(math::__main__ as MainFn)); -#[cfg(feature = "pe-module")] -add_module!(modules, "pe", pe, "pe.PE", Some("pe"), Some(pe::__main__ as MainFn)); -#[cfg(feature = "string-module")] -add_module!(modules, "string", string, "string.String", Some("string"), Some(string::__main__ as MainFn)); -#[cfg(feature = "test_proto2-module")] -add_module!(modules, "test_proto2", test_proto2, "test_proto2.TestProto2", Some("test_proto2"), Some(test_proto2::__main__ as MainFn)); -#[cfg(feature = "test_proto3-module")] -add_module!(modules, "test_proto3", test_proto3, "test_proto3.TestProto3", Some("test_proto3"), Some(test_proto3::__main__ as MainFn)); -#[cfg(feature = "time-module")] -add_module!(modules, "time", time, "time.Time", Some("time"), Some(time::__main__ as MainFn)); -#[cfg(feature = "vt-module")] -add_module!(modules, "vt", titan, "vt.titan.LiveHuntData", Some("vt"), Some(vt::__main__ as MainFn)); -} \ No newline at end of file diff --git a/lib/src/modules/console.rs b/lib/src/modules/console.rs index 73958152e..8697a8844 100644 --- a/lib/src/modules/console.rs +++ b/lib/src/modules/console.rs @@ -1,9 +1,8 @@ use std::borrow::Cow; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::console::*; -#[module_main] fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { // Nothing to do, but we have to return our protobuf Ok(Console::new()) @@ -215,3 +214,5 @@ mod tests { ); } } + +register_module!("console", Console, main); diff --git a/lib/src/modules/crx/mod.rs b/lib/src/modules/crx/mod.rs index be631bf49..1d308b6c5 100644 --- a/lib/src/modules/crx/mod.rs +++ b/lib/src/modules/crx/mod.rs @@ -2,15 +2,13 @@ This allows creating YARA rules based on metadata extracted from those files. */ - -mod parser; - use sha2::{Digest, Sha256}; use std::cell::RefCell; +use crate::mods::prelude::*; use crate::modules::crx::Crx; -use crate::modules::prelude::*; use crate::modules::protos::crx::*; +mod parser; #[cfg(test)] mod tests; @@ -20,7 +18,6 @@ thread_local!( const { RefCell::new(None) }; ); -#[module_main] fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { PERMHASH_CACHE.with(|cache| *cache.borrow_mut() = None); match parser::Crx::parse(data) { @@ -68,3 +65,5 @@ fn permhash(ctx: &ScanContext) -> Option>> { Some(Lowercase::>::new(digest)) } + +register_module!("crx", Crx, main); diff --git a/lib/src/modules/cuckoo/mod.rs b/lib/src/modules/cuckoo/mod.rs index 8a8fa58df..3b43139c6 100644 --- a/lib/src/modules/cuckoo/mod.rs +++ b/lib/src/modules/cuckoo/mod.rs @@ -1,5 +1,5 @@ use crate::compiler::RegexId; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::cuckoo::*; mod schema; @@ -22,7 +22,6 @@ fn set_local(value: schema::CuckooJson) { }); } -#[module_main] fn main(_data: &[u8], meta: Option<&[u8]>) -> Result { let meta = match meta { None | Some([]) => { @@ -269,3 +268,5 @@ fn registry_key_access_r(ctx: &ScanContext, regexp_id: RegexId) -> i64 { }) .unwrap_or(0) } + +register_module!("cuckoo", Cuckoo, main); diff --git a/lib/src/modules/dex/mod.rs b/lib/src/modules/dex/mod.rs index 08c135e18..afd723661 100644 --- a/lib/src/modules/dex/mod.rs +++ b/lib/src/modules/dex/mod.rs @@ -2,12 +2,11 @@ This allows creating YARA rules based on metadata extracted from those files. */ - use sha1::{Digest, Sha1}; use simd_adler32::Adler32; use std::cell::RefCell; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::dex::*; pub mod parser; @@ -21,7 +20,6 @@ thread_local!( const { RefCell::new(None) }; ); -#[module_main] fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { CHECKSUM_CACHE.with(|cache| *cache.borrow_mut() = None); SIGNATURE_CACHE.with(|cache| *cache.borrow_mut() = None); @@ -157,3 +155,5 @@ fn contains_class( .is_ok(), ) } + +register_module!("dex", Dex, main); diff --git a/lib/src/modules/dotnet/mod.rs b/lib/src/modules/dotnet/mod.rs index 608da3e5a..8581cc870 100644 --- a/lib/src/modules/dotnet/mod.rs +++ b/lib/src/modules/dotnet/mod.rs @@ -2,17 +2,12 @@ This allows creating YARA rules based on .NET metadata. */ - -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::dotnet::*; pub mod parser; -#[module_main] -fn main( - data: &[u8], - _meta: Option<&[u8]>, -) -> Result { +fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { match parser::Dotnet::parse(data) { Ok(dotnet) => Ok(dotnet.into()), Err(_) => { @@ -22,3 +17,5 @@ fn main( } } } + +register_module!("dotnet", Dotnet, main); diff --git a/lib/src/modules/elf/mod.rs b/lib/src/modules/elf/mod.rs index 86ad00bc5..7319df84b 100644 --- a/lib/src/modules/elf/mod.rs +++ b/lib/src/modules/elf/mod.rs @@ -11,7 +11,7 @@ use itertools::Itertools; use md5::{Digest, Md5}; use rustc_hash::FxHashSet; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::elf::*; pub mod parser; @@ -26,7 +26,6 @@ thread_local!( static TLSH_CACHE: RefCell> = const { RefCell::new(None) }; ); -#[module_main] fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { IMPORT_MD5_CACHE.with(|cache| *cache.borrow_mut() = None); TLSH_CACHE.with(|cache| *cache.borrow_mut() = None); @@ -176,3 +175,5 @@ fn telfhash(ctx: &mut ScanContext) -> Option>> { Some(Uppercase::>::new(digest)) } + +register_module!("elf", ELF, main); diff --git a/lib/src/modules/hash/mod.rs b/lib/src/modules/hash/mod.rs index 30a257a28..edc65e3cb 100644 --- a/lib/src/modules/hash/mod.rs +++ b/lib/src/modules/hash/mod.rs @@ -6,7 +6,7 @@ use rustc_hash::FxHashMap; use sha1::Sha1; use sha2::{Digest, Sha256}; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::hash::*; #[cfg(test)] @@ -29,7 +29,6 @@ thread_local!( RefCell::new(FxHashMap::default()); ); -#[module_main] fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { // With every scanned file the cache must be cleared. SHA256_CACHE.with(|cache| cache.borrow_mut().clear()); @@ -221,8 +220,8 @@ fn checksum32(data: &[u8]) -> u32 { for chunk in &mut chunks { let x = u64::from_le_bytes(chunk.try_into().unwrap()); - let pairs = (x & 0x00ff_00ff_00ff_00ff) - + ((x >> 8) & 0x00ff_00ff_00ff_00ff); + let pairs = + (x & 0x00ff_00ff_00ff_00ff) + ((x >> 8) & 0x00ff_00ff_00ff_00ff); let quads = (pairs & 0x0000_ffff_0000_ffff) + ((pairs >> 16) & 0x0000_ffff_0000_ffff); sum = sum.wrapping_add((quads & 0xffff_ffff) + (quads >> 32)); @@ -262,3 +261,5 @@ fn checksum_data(ctx: &ScanContext, offset: i64, size: i64) -> Option { fn checksum_str(ctx: &ScanContext, s: RuntimeString) -> Option { Some(checksum32(s.as_bstr(ctx).as_bytes()).into()) } + +register_module!("hash", Hash, main); diff --git a/lib/src/modules/lnk/mod.rs b/lib/src/modules/lnk/mod.rs index fd73767fe..d7e2dcff1 100644 --- a/lib/src/modules/lnk/mod.rs +++ b/lib/src/modules/lnk/mod.rs @@ -11,12 +11,10 @@ by Microsoft, and the [`non-official specification by Joachim Metz`][2]. [1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/16cb4ca1-9339-4d0c-a68d-bf1d6cc0f943 [2]: https://github.com/libyal/liblnk/blob/main/documentation/Windows%20Shortcut%20File%20(LNK)%20format.asciidoc */ - -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::lnk::*; pub mod parser; -#[module_main] fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { match parser::LnkParser::new().parse(data) { Ok(lnk) => Ok(lnk), @@ -27,3 +25,5 @@ fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { } } } + +register_module!("lnk", Lnk, main); diff --git a/lib/src/modules/lnk/parser.rs b/lib/src/modules/lnk/parser.rs index b2da26717..4fbeb03cd 100644 --- a/lib/src/modules/lnk/parser.rs +++ b/lib/src/modules/lnk/parser.rs @@ -5,7 +5,7 @@ use std::num::NonZeroUsize; use nom::bytes::complete::{take, take_while}; use nom::combinator::{cond, map_res, verify}; use nom::multi::{fold_many0, length_value, many_till}; -use nom::number::complete::{le_u128, le_u16, le_u32, le_u64}; +use nom::number::complete::{le_u16, le_u32, le_u64, le_u128}; use nom::{Err, Input, ToUsize}; use nom::{IResult, Needed, Parser}; use protobuf::EnumOrUnknown; diff --git a/lib/src/modules/macho/mod.rs b/lib/src/modules/macho/mod.rs index da8e5a852..a0ab4bd7b 100644 --- a/lib/src/modules/macho/mod.rs +++ b/lib/src/modules/macho/mod.rs @@ -7,13 +7,14 @@ use std::cell::RefCell; -use crate::modules::macho::parser::{N_EXT, N_STAB, N_TYPE}; -use crate::modules::prelude::*; -use crate::modules::protos::macho::*; use bstr::BString; use itertools::Itertools; use md5::{Digest, Md5}; +use crate::mods::prelude::*; +use crate::modules::macho::parser::{N_EXT, N_STAB, N_TYPE}; +use crate::modules::protos::macho::*; + mod parser; #[cfg(test)] mod tests; @@ -57,9 +58,10 @@ fn file_index_type(ctx: &mut ScanContext, type_arg: i64) -> Option { for i in 0..nfat as usize { if let Some(arch) = macho.fat_arch.get(i) && let Some(cputype) = arch.cputype - && cputype as i64 == type_arg { - return Some(i as i64); - } + && cputype as i64 == type_arg + { + return Some(i as i64); + } } None @@ -97,11 +99,11 @@ fn file_index_subtype( if let Some(arch) = macho.fat_arch.get(i) && let (Some(cputype), Some(cpusubtype)) = (arch.cputype, arch.cpusubtype) - && cputype as i64 == type_arg - && cpusubtype as i64 == subtype_arg - { - return Some(i as i64); - } + && cputype as i64 == type_arg + && cpusubtype as i64 == subtype_arg + { + return Some(i as i64); + } } None @@ -133,13 +135,12 @@ fn ep_for_arch_type(ctx: &mut ScanContext, type_arg: i64) -> Option { for i in 0..nfat as usize { if let Some(arch) = macho.fat_arch.get(i) && let Some(cputype) = arch.cputype - && cputype as i64 == type_arg { - let file_offset = arch.offset?; - let entry_point = macho.file.get(i)?.entry_point?; - return file_offset - .checked_add(entry_point) - .map(|sum| sum as i64); - } + && cputype as i64 == type_arg + { + let file_offset = arch.offset?; + let entry_point = macho.file.get(i)?.entry_point?; + return file_offset.checked_add(entry_point).map(|sum| sum as i64); + } } None @@ -177,15 +178,13 @@ fn ep_for_arch_subtype( if let Some(arch) = macho.fat_arch.get(i) && let (Some(cputype), Some(cpusubtype)) = (arch.cputype, arch.cpusubtype) - && cputype as i64 == type_arg - && cpusubtype as i64 == subtype_arg - { - let file_offset = arch.offset?; - let entry_point = macho.file.get(i)?.entry_point?; - return file_offset - .checked_add(entry_point) - .map(|sum| sum as i64); - } + && cputype as i64 == type_arg + && cpusubtype as i64 == subtype_arg + { + let file_offset = arch.offset?; + let entry_point = macho.file.get(i)?.entry_point?; + return file_offset.checked_add(entry_point).map(|sum| sum as i64); + } } None @@ -594,7 +593,6 @@ fn symhash(ctx: &mut ScanContext) -> Option>> { Some(Lowercase::>::new(digest)) } -#[module_main] fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { DYLIB_MD5_CACHE.with(|cache| *cache.borrow_mut() = None); ENTITLEMENT_MD5_CACHE.with(|cache| *cache.borrow_mut() = None); @@ -607,3 +605,5 @@ fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { Err(_) => Ok(Macho::new()), } } + +register_module!("macho", Macho, main); diff --git a/lib/src/modules/magic/mod.rs b/lib/src/modules/magic/mod.rs index 358404eaf..d67e60ae1 100644 --- a/lib/src/modules/magic/mod.rs +++ b/lib/src/modules/magic/mod.rs @@ -4,10 +4,10 @@ This allows creating YARA rules that use the file type provided by [libmagic][1] [1]: https://man7.org/linux/man-pages/man3/libmagic.3.html */ +use std::cell::RefCell; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::magic::*; -use std::cell::RefCell; #[cfg(feature = "logging")] use log::*; @@ -27,7 +27,6 @@ thread_local! { static MIME_TYPE_CACHE: RefCell> = const { RefCell::new(None) }; } -#[module_main] fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { // With every scanned file the cache must be cleared. TYPE_CACHE.set(None); @@ -97,3 +96,5 @@ fn get_mime_type(data: &[u8]) -> Result { MAGIC.with(|magic| magic.buffer(data)) } + +register_module!("magic", Magic, main); diff --git a/lib/src/modules/math.rs b/lib/src/modules/math.rs index 040235eaa..61ef62313 100644 --- a/lib/src/modules/math.rs +++ b/lib/src/modules/math.rs @@ -5,7 +5,7 @@ use std::f64::consts::PI; use memchr::memchr_iter; use rustc_hash::FxHashMap; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::math::*; type ByteDistribution = [u64; 256]; @@ -14,11 +14,11 @@ const DISTRIBUTION_CACHE_MIN_LEN: usize = 4096; const DISTRIBUTION_CACHE_MAX_ENTRIES: usize = 8; thread_local!( - static DISTRIBUTION_CACHE: RefCell> = - RefCell::new(FxHashMap::default()); + static DISTRIBUTION_CACHE: RefCell< + FxHashMap<(usize, usize), ByteDistribution>, + > = RefCell::new(FxHashMap::default()); ); -#[module_main] fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { DISTRIBUTION_CACHE.with(|cache| cache.borrow_mut().clear()); @@ -80,11 +80,7 @@ fn to_string_base( /// Converts a boolean to an integer (0 or 1). #[module_export] fn to_number(_ctx: &ScanContext, b: bool) -> i64 { - if b { - 1 - } else { - 0 - } + if b { 1 } else { 0 } } /// Counts the occurrences of a byte in a range of the scanned data. @@ -258,7 +254,11 @@ fn monte_carlo_pi_string(ctx: &ScanContext, s: RuntimeString) -> Option { monte_carlo_pi(s.as_bstr(ctx).as_bytes()) } -fn data_range(data: &[u8], offset: i64, length: i64) -> Option<(usize, usize)> { +fn data_range( + data: &[u8], + offset: i64, + length: i64, +) -> Option<(usize, usize)> { let length: usize = length.try_into().ok()?; let start: usize = offset.try_into().ok()?; let end = cmp::min(data.len(), start.saturating_add(length)); @@ -415,11 +415,7 @@ fn serial_correlation(data: &[u8]) -> Option { let scc = (len * adjacent_product_sum - byte_sum_squared) / (len * byte_square_sum - byte_sum_squared); - if scc.is_nan() { - Some(-100000.0) - } else { - Some(scc) - } + if scc.is_nan() { Some(-100000.0) } else { Some(scc) } } fn monte_carlo_pi(data: &[u8]) -> Option { @@ -1013,3 +1009,5 @@ mod tests { ); } } + +register_module!("math", Math, main); diff --git a/lib/src/modules/mod.rs b/lib/src/modules/mod.rs index d4038f18c..d6dbcdfed 100644 --- a/lib/src/modules/mod.rs +++ b/lib/src/modules/mod.rs @@ -1,8 +1,5 @@ -use std::sync::LazyLock; - use protobuf::MessageDyn; use protobuf::reflect::MessageDescriptor; -use rustc_hash::FxHashMap; use thiserror::Error; @@ -19,19 +16,6 @@ mod tests; pub(crate) mod field_docs; -#[allow(unused_imports)] -pub(crate) mod prelude { - pub(crate) use crate::scanner::ScanContext; - pub(crate) use crate::wasm::runtime::Caller; - pub(crate) use crate::wasm::string::FixedLenString; - pub(crate) use crate::wasm::string::RuntimeString; - pub(crate) use crate::wasm::string::String as _; - pub(crate) use crate::wasm::string::{Lowercase, Uppercase}; - pub(crate) use crate::wasm::*; - pub(crate) use bstr::ByteSlice; - - pub(crate) use yara_x_macros::{module_export, module_main, wasm_export}; -} include!("modules.rs"); /// Enum describing errors occurred in modules. @@ -52,100 +36,123 @@ pub enum ModuleError { }, } -/// Signature of a module's main function. -type MainFn = - fn(&[u8], Option<&[u8]>) -> Result, ModuleError>; +/// The trait implemented by all registered modules. +pub trait RegisteredModule: Send + Sync { + /// Name used for the module in `import` statements (e.g. `"my_module"`). + fn name(&self) -> &'static str; + + /// Returns the descriptor of the protobuf message that defines the + /// module's root structure. + fn root_descriptor(&self) -> MessageDescriptor; + + /// Main function called every time YARA scans some data, before + /// evaluating the rules. Set to `None` for data-only modules. + fn main_fn( + &self, + data: &[u8], + meta: Option<&[u8]>, + ) -> Option, ModuleError>>; + + /// Rust module path of the submodule inside the external crate that + /// contains functions registered with `#[module_export(yara_x_crate = ...)]`. + /// + /// Must match the value that `module_path!()` expands to at those + /// functions' definition site (e.g. `"my_crate::my_mod"`). Set to + /// `None` for data-only modules that export no callable functions. + fn rust_module_name(&self) -> Option<&'static str>; +} -/// A structure describing a YARA module. -pub(crate) struct Module { - /// Pointer to the module's main function. - pub main_fn: Option, - /// Name of the Rust module, if any, that contains code for this YARA - /// module (e.g: "test_proto2"). +/// Main function in a YARA module. +pub type ModuleMainFn = fn(&[u8], Option<&[u8]>) -> Result; + +/// Description of a YARA module, generic over the type `T` returned by the +/// main function. +pub struct Module +where + T: protobuf::MessageFull + 'static, +{ + /// Name used for the module in `import` statements (e.g. `"my_module"`). + pub name: &'static str, + /// Main function called every time YARA scans some data, before + /// evaluating the rules. Set to `None` for data-only modules. + pub main_fn: Option>, + /// Rust module path of the submodule inside the external crate that + /// contains functions registered with `#[module_export(yara_x_crate = ...)]`. pub rust_module_name: Option<&'static str>, - /// A [`MessageDescriptor`] that describes the module's structure. This - /// corresponds to the protobuf message declared in the "root_message" - /// for the YARA module. It allows iterating the fields declared by the - /// module and obtaining their names and types. - pub root_struct_descriptor: MessageDescriptor, } -/// Macro that adds a module to the `BUILTIN_MODULES` map. -/// -/// This macro is used by `add_modules.rs`, a file that is automatically -/// generated by `build.rs` based on the Protocol Buffers defined in the -/// `src/modules/protos` directory. -/// -/// # Example -/// -/// add_module!(modules, "test", test, "Test", test_mod, Some(test::main as -/// MainFn)); -macro_rules! add_module { - ($modules:expr, $name:literal, $proto:ident, $root_message:literal, $rust_module_name:expr, $main_fn:expr) => {{ - use std::stringify; - let root_struct_descriptor = protos::$proto::file_descriptor() - // message_by_full_name expects a dot (.) at the beginning - // of the name. - .message_by_full_name(format!(".{}", $root_message).as_str()) - .expect(format!( - "`root_message` option in protobuf `{}` is wrong, message `{}` is not defined", - stringify!($proto), - $root_message - ).as_str()); - - $modules.insert( - $name, - Module { - main_fn: $main_fn, - rust_module_name: $rust_module_name, - root_struct_descriptor, - }, - ); - }}; +impl RegisteredModule for Module +where + T: protobuf::MessageFull + 'static, +{ + fn name(&self) -> &'static str { + self.name + } + + fn root_descriptor(&self) -> MessageDescriptor { + T::descriptor() + } + + fn main_fn( + &self, + data: &[u8], + meta: Option<&[u8]>, + ) -> Option, ModuleError>> { + self.main_fn.map(|f| { + f(data, meta).map(|ok| Box::new(ok) as Box) + }) + } + + fn rust_module_name(&self) -> Option<&'static str> { + self.rust_module_name + } } -/// `BUILTIN_MODULES` is a static, global map where keys are module names -/// and values are [`Module`] structures that describe a YARA module. +/// Macro used to register a YARA module. /// -/// This table is populated with the modules defined by a `.proto` file in -/// `src/modules/protos`. Each `.proto` file that contains a statement like -/// the following one defines a YARA module: +/// # Examples /// -/// ```protobuf -/// option (yara.module_options) = { -/// name : "foo" -/// root_message: "Foo" -/// rust_module: "foo" -/// }; +/// Registering a module with a main function: +/// +/// ```ignore +/// register_module!("my_module", MyModuleProto, main); /// ``` /// -/// The `name` field is the module's name (i.e: the name used in `import` -/// statements), which is also the key in `BUILTIN_MODULES`. `root_message` -/// is the name of the message that describes the module's structure. This -/// is required because a `.proto` file can define more than one message. +/// Registering a data-only module with no main function: /// -/// `rust_module` is the name of the Rust module where functions exported -/// by the YARA module are defined. This field is optional, if not provided -/// the module is considered a data-only module. -pub(crate) static BUILTIN_MODULES: LazyLock> = - LazyLock::new(|| { - let mut modules = FxHashMap::default(); - // The `add_modules.rs` file is automatically generated at compile time - // by `build.rs`. This is an example of how `add_modules.rs` looks like: - // - // { - // #[cfg(feature = "pe_module")] - // add_module!(modules, "pe", pe, "pe.PE", Some("pe"), Some(pe::__main__ as MainFn)); - // - // #[cfg(feature = "elf_module")] - // add_module!(modules, "elf", elf, "elf.ELF", Some("elf"), Some(elf::__main__ as MainFn)); - // } - // - // `add_modules.rs` will contain an `add_module!` statement for each - // protobuf in `src/modules/protos` defining a YARA module. - include!("add_modules.rs"); - modules - }); +/// ```ignore +/// register_module!("my_module", MyModuleProto); +/// ``` +#[macro_export] +macro_rules! register_module { + ($name:literal, $root_message:ty, $main_fn:path) => { + $crate::mods::prelude::inventory::submit! { + &$crate::mods::prelude::Module::<$root_message> { + name: $name, + main_fn: Some($main_fn), + rust_module_name: Some(module_path!()), + } as &dyn $crate::mods::prelude::RegisteredModule + } + }; + ($name:literal, $root_message:ty) => { + $crate::mods::prelude::inventory::submit! { + &$crate::mods::prelude::Module::<$root_message> { + name: $name, + main_fn: None, + rust_module_name: None, + } as &dyn $crate::mods::prelude::RegisteredModule + } + }; +} + +inventory::collect!(&'static dyn RegisteredModule); + +/// Returns an iterator over all registered modules. +#[inline] +pub(crate) fn registered_modules() +-> impl Iterator { + inventory::iter::<&'static dyn RegisteredModule>().copied() +} pub mod mods { /*! Utility functions and structures that allow invoking YARA modules directly. @@ -183,7 +190,6 @@ pub mod mods { pub use super::protos::dex; /// Data structure returned by the `dex` module. pub use super::protos::dex::Dex; - /// Data structures defined by the `dotnet` module. /// /// The main structure produced by the module is [`dotnet::Dotnet`]. The @@ -192,7 +198,6 @@ pub mod mods { pub use super::protos::dotnet; /// Data structure returned by the `dotnet` module. pub use super::protos::dotnet::Dotnet; - /// Data structures defined by the `elf` module. /// /// The main structure produced by the module is [`elf::ELF`]. The rest of @@ -201,7 +206,6 @@ pub mod mods { pub use super::protos::elf; /// Data structure returned by the `elf` module. pub use super::protos::elf::ELF; - /// Data structures defined by the `lnk` module. /// /// The main structure produced by the module is [`lnk::Lnk`]. The rest of @@ -289,12 +293,11 @@ pub mod mods { ) -> Option> { let descriptor = T::descriptor(); let proto_name = descriptor.full_name(); - let (_, module) = - super::BUILTIN_MODULES.iter().find(|(_, module)| { - module.root_struct_descriptor.full_name() == proto_name - })?; - module.main_fn?(data, meta).ok() + let module = super::registered_modules() + .find(|m| m.root_descriptor().full_name() == proto_name)?; + + module.main_fn(data, meta)?.ok() } /// Invokes all YARA modules and returns the data produced by them. @@ -319,21 +322,55 @@ pub mod mods { info } - /// Iterator over built-in module names. + /// Iterator over all registered module names. /// /// See the "debug modules" command. pub fn module_names() -> impl Iterator { use itertools::Itertools; - super::BUILTIN_MODULES.keys().sorted_by_key(|k| **k).copied() + super::registered_modules().map(|m| m.name()).sorted() } /// Returns the definition of the module with the given name. pub fn module_definition(name: &str) -> Option { - use crate::types; use std::rc::Rc; - super::BUILTIN_MODULES - .get(name) - .map(|m| reflect::Struct::new(Rc::::from(m))) + super::registered_modules() + .find(|m| m.name() == name) + .map(|m| reflect::Struct::new(Rc::::from(m))) + } + + /// Everything needed to implement your own YARA-X modules. + #[allow(unused_imports)] + #[allow(missing_docs)] + pub mod prelude { + pub use crate::modules::Module; + pub use crate::modules::ModuleError; + pub use crate::modules::RegisteredModule; + pub use crate::register_module; + pub use crate::wasm::runtime::Caller; + pub use crate::wasm::string::FixedLenString; + pub use crate::wasm::string::RuntimeString; + pub use crate::wasm::string::String as _; + pub use crate::wasm::string::{Lowercase, Uppercase}; + pub use crate::wasm::*; + pub use bstr::ByteSlice; + pub use inventory; + pub use protobuf::MessageFull; + pub use yara_x_macros::wasm_export; + + /// Opaque scan context passed as first argument to functions exported from a + /// [`Module`] via `#[module_export]`. + /// + /// Functions only receive a reference to it; all fields are private. + pub type ScanContext<'r, 'd> = crate::scanner::ScanContext<'r, 'd>; + + /// Attribute macro for exporting a callable function from a [`Module`]. + /// + /// ```ignore + /// use yara_x::mods::prelude::*; + /// #[module_export] + /// fn add(_ctx: &ScanContext, a: i64, b: i64) -> i64 { a + b } + /// ``` + pub use yara_x_macros::module_export; } /// Types that allow for module introspection. diff --git a/lib/src/modules/pe/mod.rs b/lib/src/modules/pe/mod.rs index 337e698bf..142d1ad6d 100644 --- a/lib/src/modules/pe/mod.rs +++ b/lib/src/modules/pe/mod.rs @@ -17,7 +17,7 @@ use nom::combinator::map; use nom::number::complete::{le_u16, le_u32}; use crate::compiler::RegexId; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::pe::*; use crate::types::Struct; @@ -35,7 +35,6 @@ thread_local!( static CHECKSUM_CACHE: RefCell> = const { RefCell::new(None) }; ); -#[module_main] fn main(data: &[u8], _meta: Option<&[u8]>) -> Result { IMPHASH_CACHE.with(|cache| *cache.borrow_mut() = None); CHECKSUM_CACHE.with(|cache| *cache.borrow_mut() = None); @@ -854,3 +853,5 @@ fn exports_impl( }) .map_or(Some((false, 0)), |(position, _)| Some((true, position))) } + +register_module!("pe", PE, main); diff --git a/lib/src/modules/protos/console.proto b/lib/src/modules/protos/console.proto index 40d615584..d411f946c 100644 --- a/lib/src/modules/protos/console.proto +++ b/lib/src/modules/protos/console.proto @@ -6,7 +6,6 @@ package console; option (yara.module_options) = { name : "console" root_message: "console.Console" - rust_module: "console" cargo_feature: "console-module" }; diff --git a/lib/src/modules/protos/crx.proto b/lib/src/modules/protos/crx.proto index 13283d82c..1a7de127d 100644 --- a/lib/src/modules/protos/crx.proto +++ b/lib/src/modules/protos/crx.proto @@ -6,7 +6,6 @@ package crx; option (yara.module_options) = { name : "crx" root_message: "crx.Crx" - rust_module: "crx" cargo_feature: "crx-module" }; diff --git a/lib/src/modules/protos/cuckoo.proto b/lib/src/modules/protos/cuckoo.proto index 23e911616..6c7c46f0a 100644 --- a/lib/src/modules/protos/cuckoo.proto +++ b/lib/src/modules/protos/cuckoo.proto @@ -6,7 +6,6 @@ package cuckoo; option (yara.module_options) = { name : "cuckoo" root_message: "cuckoo.Cuckoo" - rust_module: "cuckoo" cargo_feature: "cuckoo-module" }; diff --git a/lib/src/modules/protos/dex.proto b/lib/src/modules/protos/dex.proto index 9738e60ee..acb238c41 100644 --- a/lib/src/modules/protos/dex.proto +++ b/lib/src/modules/protos/dex.proto @@ -6,7 +6,6 @@ package dex; option (yara.module_options) = { name : "dex", root_message: "dex.Dex", - rust_module: "dex", cargo_feature: "dex-module" }; diff --git a/lib/src/modules/protos/dotnet.proto b/lib/src/modules/protos/dotnet.proto index 8b78d7afe..e1266f3fd 100644 --- a/lib/src/modules/protos/dotnet.proto +++ b/lib/src/modules/protos/dotnet.proto @@ -7,7 +7,6 @@ package dotnet; option (yara.module_options) = { name : "dotnet" root_message: "dotnet.Dotnet" - rust_module: "dotnet" cargo_feature: "dotnet-module" }; diff --git a/lib/src/modules/protos/elf.proto b/lib/src/modules/protos/elf.proto index 1847beb74..36162aa97 100644 --- a/lib/src/modules/protos/elf.proto +++ b/lib/src/modules/protos/elf.proto @@ -6,7 +6,6 @@ package elf; option (yara.module_options) = { name : "elf" root_message: "elf.ELF" - rust_module: "elf" cargo_feature: "elf-module" }; diff --git a/lib/src/modules/protos/generated/console.rs b/lib/src/modules/protos/generated/console.rs index 7f426eec5..b69bdc20f 100644 --- a/lib/src/modules/protos/generated/console.rs +++ b/lib/src/modules/protos/generated/console.rs @@ -128,9 +128,9 @@ impl ::protobuf::reflect::ProtobufValue for Console { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\rconsole.proto\x12\x07console\x1a\nyara.proto\"\t\n\x07ConsoleB7\xfa\ - \x92\x193\n\x07console\x12\x0fconsole.Console\x1a\x07console\"\x0econsol\ - e-moduleb\x06proto2\ + \n\rconsole.proto\x12\x07console\x1a\nyara.proto\"\t\n\x07ConsoleB.\xfa\ + \x92\x19*\n\x07console\x12\x0fconsole.Console\x1a\x0econsole-moduleb\x06\ + proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/crx.rs b/lib/src/modules/protos/generated/crx.rs index f0f026df0..1863b215f 100644 --- a/lib/src/modules/protos/generated/crx.rs +++ b/lib/src/modules/protos/generated/crx.rs @@ -1558,8 +1558,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ gnedHeaderData\"Q\n\x12AsymmetricKeyProof\x12\x1d\n\npublic_key\x18\x01\ \x20\x01(\x0cR\tpublicKey\x12\x1c\n\tsignature\x18\x02\x20\x01(\x0cR\tsi\ gnature\"#\n\nSignedData\x12\x15\n\x06crx_id\x18\x01\x20\x01(\x0cR\x05cr\ - xIdB#\xfa\x92\x19\x1f\n\x03crx\x12\x07crx.Crx\x1a\x03crx\"\ncrx-moduleb\ - \x06proto2\ + xIdB\x1e\xfa\x92\x19\x1a\n\x03crx\x12\x07crx.Crx\x1a\ncrx-moduleb\x06pro\ + to2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/cuckoo.rs b/lib/src/modules/protos/generated/cuckoo.rs index 270d090bb..71c3749f5 100644 --- a/lib/src/modules/protos/generated/cuckoo.rs +++ b/lib/src/modules/protos/generated/cuckoo.rs @@ -128,9 +128,8 @@ impl ::protobuf::reflect::ProtobufValue for Cuckoo { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0ccuckoo.proto\x12\x06cuckoo\x1a\nyara.proto\"\x08\n\x06CuckooB2\xfa\ - \x92\x19.\n\x06cuckoo\x12\rcuckoo.Cuckoo\x1a\x06cuckoo\"\rcuckoo-moduleb\ - \x06proto2\ + \n\x0ccuckoo.proto\x12\x06cuckoo\x1a\nyara.proto\"\x08\n\x06CuckooB*\xfa\ + \x92\x19&\n\x06cuckoo\x12\rcuckoo.Cuckoo\x1a\rcuckoo-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/dex.rs b/lib/src/modules/protos/generated/dex.rs index ed23669ca..c41366108 100644 --- a/lib/src/modules/protos/generated/dex.rs +++ b/lib/src/modules/protos/generated/dex.rs @@ -2864,8 +2864,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ DEBUG_INFO_ITEM\x10\x83@\x12\x19\n\x14TYPE_ANNOTATION_ITEM\x10\x84@\x12\ \x1c\n\x17TYPE_ENCODED_ARRAY_ITEM\x10\x85@\x12$\n\x1fTYPE_ANNOTATIONS_DI\ RECTORY_ITEM\x10\x86@\x12$\n\x1eTYPE_HIDDENAPI_CLASS_DATA_ITEM\x10\x80\ - \xe0\x03\x1a\x06\x92\x93\x19\x02\x10\x01B#\xfa\x92\x19\x1f\n\x03dex\x12\ - \x07dex.Dex\x1a\x03dex\"\ndex-moduleb\x06proto2\ + \xe0\x03\x1a\x06\x92\x93\x19\x02\x10\x01B\x1e\xfa\x92\x19\x1a\n\x03dex\ + \x12\x07dex.Dex\x1a\ndex-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/dotnet.rs b/lib/src/modules/protos/generated/dotnet.rs index 5eae391ac..289ad36cd 100644 --- a/lib/src/modules/protos/generated/dotnet.rs +++ b/lib/src/modules/protos/generated/dotnet.rs @@ -3607,8 +3607,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ers\x18\n\x20\x03(\tR\x11genericParameters\x12-\n\nparameters\x18\x0b\ \x20\x03(\x0b2\r.dotnet.ParamR\nparameters\"/\n\x05Param\x12\x12\n\x04na\ me\x18\x01\x20\x02(\tR\x04name\x12\x12\n\x04type\x18\x02\x20\x01(\tR\x04\ - typeB2\xfa\x92\x19.\n\x06dotnet\x12\rdotnet.Dotnet\x1a\x06dotnet\"\rdotn\ - et-moduleb\x06proto2\ + typeB*\xfa\x92\x19&\n\x06dotnet\x12\rdotnet.Dotnet\x1a\rdotnet-moduleb\ + \x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/elf.rs b/lib/src/modules/protos/generated/elf.rs index e79696e09..49c22d91f 100644 --- a/lib/src/modules/protos/generated/elf.rs +++ b/lib/src/modules/protos/generated/elf.rs @@ -3549,8 +3549,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x06\x12\x12\n\nDT_VERNEED\x10\xfe\xff\xff\xff\x06\x12\x15\n\rDT_VERNEED\ NUM\x10\xff\xff\xff\xff\x06\x12\x11\n\tDT_LOPROC\x10\x80\x80\x80\x80\x07\ \x12\x11\n\tDT_HIPROC\x10\xff\xff\xff\xff\x07\x1a\x06\x92\x93\x19\x02\ - \x10\x01B#\xfa\x92\x19\x1f\n\x03elf\x12\x07elf.ELF\x1a\x03elf\"\nelf-mod\ - uleb\x06proto2\ + \x10\x01B\x1e\xfa\x92\x19\x1a\n\x03elf\x12\x07elf.ELF\x1a\nelf-moduleb\ + \x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/hash.rs b/lib/src/modules/protos/generated/hash.rs index 999d245be..3001a80cc 100644 --- a/lib/src/modules/protos/generated/hash.rs +++ b/lib/src/modules/protos/generated/hash.rs @@ -128,8 +128,8 @@ impl ::protobuf::reflect::ProtobufValue for Hash { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\nhash.proto\x12\x04hash\x1a\nyara.proto\"\x06\n\x04HashB(\xfa\x92\x19\ - $\n\x04hash\x12\thash.Hash\x1a\x04hash\"\x0bhash-moduleb\x06proto2\ + \n\nhash.proto\x12\x04hash\x1a\nyara.proto\"\x06\n\x04HashB\"\xfa\x92\ + \x19\x1e\n\x04hash\x12\thash.Hash\x1a\x0bhash-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/lnk.rs b/lib/src/modules/protos/generated/lnk.rs index 50110f2e1..d083a0da7 100644 --- a/lib/src/modules/protos/generated/lnk.rs +++ b/lib/src/modules/protos/generated/lnk.rs @@ -1791,8 +1791,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ _ACTIVE\x10\x07*g\n\tDriveType\x12\x0b\n\x07UNKNOWN\x10\0\x12\x0f\n\x0bN\ O_ROOT_DIR\x10\x01\x12\r\n\tREMOVABLE\x10\x02\x12\t\n\x05FIXED\x10\x03\ \x12\n\n\x06REMOTE\x10\x04\x12\t\n\x05CDROM\x10\x05\x12\x0b\n\x07RAMDISK\ - \x10\x06B#\xfa\x92\x19\x1f\n\x03lnk\x12\x07lnk.Lnk\x1a\x03lnk\"\nlnk-mod\ - uleb\x06proto2\ + \x10\x06B\x1e\xfa\x92\x19\x1a\n\x03lnk\x12\x07lnk.Lnk\x1a\nlnk-moduleb\ + \x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/macho.rs b/lib/src/modules/protos/generated/macho.rs index 100c50947..5c2b41a15 100644 --- a/lib/src/modules/protos/generated/macho.rs +++ b/lib/src/modules/protos/generated/macho.rs @@ -9064,8 +9064,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x04\x12\x15\n\x10S_ATTR_LOC_RELOC\x10\x80\x02\x1a\x06\x92\x93\x19\x02\ \x10\x01*E\n\nDeviceType\x12\n\n\x06MACOSX\x10$\x12\x0c\n\x08IPHONEOS\ \x10%\x12\x08\n\x04TVOS\x10/\x12\x0b\n\x07WATCHOS\x100\x1a\x06\x92\x93\ - \x19\x02\x10\x01B-\xfa\x92\x19)\n\x05macho\x12\x0bmacho.Macho\x1a\x05mac\ - ho\"\x0cmacho-moduleb\x06proto2\ + \x19\x02\x10\x01B&\xfa\x92\x19\"\n\x05macho\x12\x0bmacho.Macho\x1a\x0cma\ + cho-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/magic.rs b/lib/src/modules/protos/generated/magic.rs index 9af7d4356..d65179a20 100644 --- a/lib/src/modules/protos/generated/magic.rs +++ b/lib/src/modules/protos/generated/magic.rs @@ -128,9 +128,8 @@ impl ::protobuf::reflect::ProtobufValue for Magic { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0bmagic.proto\x12\x05magic\x1a\nyara.proto\"\x07\n\x05MagicB-\xfa\ - \x92\x19)\n\x05magic\x12\x0bmagic.Magic\x1a\x05magic\"\x0cmagic-moduleb\ - \x06proto2\ + \n\x0bmagic.proto\x12\x05magic\x1a\nyara.proto\"\x07\n\x05MagicB&\xfa\ + \x92\x19\"\n\x05magic\x12\x0bmagic.Magic\x1a\x0cmagic-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/math.rs b/lib/src/modules/protos/generated/math.rs index c1cb4dadd..a8c12c135 100644 --- a/lib/src/modules/protos/generated/math.rs +++ b/lib/src/modules/protos/generated/math.rs @@ -187,8 +187,8 @@ impl Consts { static file_descriptor_proto_data: &'static [u8] = b"\ \n\nmath.proto\x12\x04math\x1a\nyara.proto\"\x06\n\x04Math*/\n\x06Consts\ \x12\x1d\n\nMEAN_BYTES\x10\0\x1a\r\x9a\x93\x19\t\x11\0\0\0\0\0\xe0_@\x1a\ - \x06\x92\x93\x19\x02\x10\x01B(\xfa\x92\x19$\n\x04math\x12\tmath.Math\x1a\ - \x04math\"\x0bmath-moduleb\x06proto2\ + \x06\x92\x93\x19\x02\x10\x01B\"\xfa\x92\x19\x1e\n\x04math\x12\tmath.Math\ + \x1a\x0bmath-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/pe.rs b/lib/src/modules/protos/generated/pe.rs index 8ffafd3f9..b634ee54a 100644 --- a/lib/src/modules/protos/generated/pe.rs +++ b/lib/src/modules/protos/generated/pe.rs @@ -8985,8 +8985,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x07NO_BIND\x10\x80\x10\x12\x11\n\x0cAPPCONTAINER\x10\x80\x20\x12\x0f\n\ \nWDM_DRIVER\x10\x80@\x12\x0e\n\x08GUARD_CF\x10\x80\x80\x01\x12\x1b\n\ \x15TERMINAL_SERVER_AWARE\x10\x80\x80\x02\x1a\x06\x92\x93\x19\x02\x10\ - \x01B\x1e\xfa\x92\x19\x1a\n\x02pe\x12\x05pe.PE\x1a\x02pe\"\tpe-moduleb\ - \x06proto2\ + \x01B\x1a\xfa\x92\x19\x16\n\x02pe\x12\x05pe.PE\x1a\tpe-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/string.rs b/lib/src/modules/protos/generated/string.rs index f14f36cd0..211b1731a 100644 --- a/lib/src/modules/protos/generated/string.rs +++ b/lib/src/modules/protos/generated/string.rs @@ -128,9 +128,8 @@ impl ::protobuf::reflect::ProtobufValue for String { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0cstring.proto\x12\x06string\x1a\nyara.proto\"\x08\n\x06StringB2\xfa\ - \x92\x19.\n\x06string\x12\rstring.String\x1a\x06string\"\rstring-moduleb\ - \x06proto2\ + \n\x0cstring.proto\x12\x06string\x1a\nyara.proto\"\x08\n\x06StringB*\xfa\ + \x92\x19&\n\x06string\x12\rstring.String\x1a\rstring-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/test_proto2.rs b/lib/src/modules/protos/generated/test_proto2.rs index 9fa71d8e3..ba9465894 100644 --- a/lib/src/modules/protos/generated/test_proto2.rs +++ b/lib/src/modules/protos/generated/test_proto2.rs @@ -3524,8 +3524,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ M_1\x10\x01*9\n\x13TopLevelEnumeration\x12\x10\n\x0bITEM_0x1000\x10\x80\ \x20\x12\x10\n\x0bITEM_0x2000\x10\x80@*C\n\x11InlineEnumeration\x12\x12\ \n\rINLINE_0x1000\x10\x80\x20\x12\x12\n\rINLINE_0x2000\x10\x80@\x1a\x06\ - \x92\x93\x19\x02\x10\x01BJ\xfa\x92\x19F\n\x0btest_proto2\x12\x16test_pro\ - to2.TestProto2\x1a\x0btest_proto2\"\x12test_proto2-moduleb\x06proto2\ + \x92\x93\x19\x02\x10\x01B=\xfa\x92\x199\n\x0btest_proto2\x12\x16test_pro\ + to2.TestProto2\x1a\x12test_proto2-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/test_proto3.rs b/lib/src/modules/protos/generated/test_proto3.rs index 360b38165..5de0111a5 100644 --- a/lib/src/modules/protos/generated/test_proto3.rs +++ b/lib/src/modules/protos/generated/test_proto3.rs @@ -881,9 +881,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x1d\n\nstring_bar\x18>\x20\x01(\tR\tstringBar\x12!\n\x0cstring_undef\ \x18?\x20\x01(\tR\x0bstringUndef\x12\x1b\n\tbytes_foo\x18@\x20\x01(\x0cR\ \x08bytesFoo\x12\x1b\n\tbytes_bar\x18A\x20\x01(\x0cR\x08bytesBar\x12\x1f\ - \n\x0bbytes_undef\x18B\x20\x01(\x0cR\nbytesUndefBJ\xfa\x92\x19F\n\x0btes\ - t_proto3\x12\x16test_proto3.TestProto3\x1a\x0btest_proto3\"\x12test_prot\ - o3-moduleb\x06proto3\ + \n\x0bbytes_undef\x18B\x20\x01(\x0cR\nbytesUndefB=\xfa\x92\x199\n\x0btes\ + t_proto3\x12\x16test_proto3.TestProto3\x1a\x12test_proto3-moduleb\x06pro\ + to3\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/time.rs b/lib/src/modules/protos/generated/time.rs index 94ea01ac2..fb1ef74e3 100644 --- a/lib/src/modules/protos/generated/time.rs +++ b/lib/src/modules/protos/generated/time.rs @@ -128,8 +128,8 @@ impl ::protobuf::reflect::ProtobufValue for Time { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\ntime.proto\x12\x04time\x1a\nyara.proto\"\x06\n\x04TimeB(\xfa\x92\x19\ - $\n\x04time\x12\ttime.Time\x1a\x04time\"\x0btime-moduleb\x06proto2\ + \n\ntime.proto\x12\x04time\x1a\nyara.proto\"\x06\n\x04TimeB\"\xfa\x92\ + \x19\x1e\n\x04time\x12\ttime.Time\x1a\x0btime-moduleb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/titan.rs b/lib/src/modules/protos/generated/titan.rs index d15308f19..7940a3f03 100644 --- a/lib/src/modules/protos/generated/titan.rs +++ b/lib/src/modules/protos/generated/titan.rs @@ -1629,8 +1629,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ f\x1a=\n\x0fSignaturesEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\ \x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value:\x028\x01\x1a;\n\rExift\ oolEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\ - \x18\x02\x20\x01(\tR\x05value:\x028\x01B.\xfa\x92\x19*\n\x02vt\x12\x15vt\ - .titan.LiveHuntData\x1a\x02vt\"\tvt-moduleb\x06proto3\ + \x18\x02\x20\x01(\tR\x05value:\x028\x01B*\xfa\x92\x19&\n\x02vt\x12\x15vt\ + .titan.LiveHuntData\x1a\tvt-moduleb\x06proto3\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/generated/yara.rs b/lib/src/modules/protos/generated/yara.rs index edf8d628c..708be5c59 100644 --- a/lib/src/modules/protos/generated/yara.rs +++ b/lib/src/modules/protos/generated/yara.rs @@ -32,8 +32,6 @@ pub struct ModuleOptions { pub name: ::std::option::Option<::std::string::String>, // @@protoc_insertion_point(field:yara.ModuleOptions.root_message) pub root_message: ::std::option::Option<::std::string::String>, - // @@protoc_insertion_point(field:yara.ModuleOptions.rust_module) - pub rust_module: ::std::option::Option<::std::string::String>, // @@protoc_insertion_point(field:yara.ModuleOptions.cargo_feature) pub cargo_feature: ::std::option::Option<::std::string::String>, // special fields @@ -124,43 +122,7 @@ impl ModuleOptions { self.root_message.take().unwrap_or_else(|| ::std::string::String::new()) } - // optional string rust_module = 3; - - pub fn rust_module(&self) -> &str { - match self.rust_module.as_ref() { - Some(v) => v, - None => "", - } - } - - pub fn clear_rust_module(&mut self) { - self.rust_module = ::std::option::Option::None; - } - - pub fn has_rust_module(&self) -> bool { - self.rust_module.is_some() - } - - // Param is passed by value, moved - pub fn set_rust_module(&mut self, v: ::std::string::String) { - self.rust_module = ::std::option::Option::Some(v); - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_rust_module(&mut self) -> &mut ::std::string::String { - if self.rust_module.is_none() { - self.rust_module = ::std::option::Option::Some(::std::string::String::new()); - } - self.rust_module.as_mut().unwrap() - } - - // Take field - pub fn take_rust_module(&mut self) -> ::std::string::String { - self.rust_module.take().unwrap_or_else(|| ::std::string::String::new()) - } - - // optional string cargo_feature = 4; + // optional string cargo_feature = 3; pub fn cargo_feature(&self) -> &str { match self.cargo_feature.as_ref() { @@ -197,7 +159,7 @@ impl ModuleOptions { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(4); + let mut fields = ::std::vec::Vec::with_capacity(3); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "name", @@ -209,11 +171,6 @@ impl ModuleOptions { |m: &ModuleOptions| { &m.root_message }, |m: &mut ModuleOptions| { &mut m.root_message }, )); - fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "rust_module", - |m: &ModuleOptions| { &m.rust_module }, - |m: &mut ModuleOptions| { &mut m.rust_module }, - )); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "cargo_feature", |m: &ModuleOptions| { &m.cargo_feature }, @@ -250,9 +207,6 @@ impl ::protobuf::Message for ModuleOptions { self.root_message = ::std::option::Option::Some(is.read_string()?); }, 26 => { - self.rust_module = ::std::option::Option::Some(is.read_string()?); - }, - 34 => { self.cargo_feature = ::std::option::Option::Some(is.read_string()?); }, tag => { @@ -273,11 +227,8 @@ impl ::protobuf::Message for ModuleOptions { if let Some(v) = self.root_message.as_ref() { my_size += ::protobuf::rt::string_size(2, &v); } - if let Some(v) = self.rust_module.as_ref() { - my_size += ::protobuf::rt::string_size(3, &v); - } if let Some(v) = self.cargo_feature.as_ref() { - my_size += ::protobuf::rt::string_size(4, &v); + my_size += ::protobuf::rt::string_size(3, &v); } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); @@ -291,11 +242,8 @@ impl ::protobuf::Message for ModuleOptions { if let Some(v) = self.root_message.as_ref() { os.write_string(2, v)?; } - if let Some(v) = self.rust_module.as_ref() { - os.write_string(3, v)?; - } if let Some(v) = self.cargo_feature.as_ref() { - os.write_string(4, v)?; + os.write_string(3, v)?; } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) @@ -316,7 +264,6 @@ impl ::protobuf::Message for ModuleOptions { fn clear(&mut self) { self.name = ::std::option::Option::None; self.root_message = ::std::option::Option::None; - self.rust_module = ::std::option::Option::None; self.cargo_feature = ::std::option::Option::None; self.special_fields.clear(); } @@ -325,7 +272,6 @@ impl ::protobuf::Message for ModuleOptions { static instance: ModuleOptions = ModuleOptions { name: ::std::option::Option::None, root_message: ::std::option::Option::None, - rust_module: ::std::option::Option::None, cargo_feature: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; @@ -1802,36 +1748,35 @@ pub mod exts { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\nyara.proto\x12\x04yara\x1a\x20google/protobuf/descriptor.proto\"\x8c\ - \x01\n\rModuleOptions\x12\x12\n\x04name\x18\x01\x20\x02(\tR\x04name\x12!\ - \n\x0croot_message\x18\x02\x20\x02(\tR\x0brootMessage\x12\x1f\n\x0brust_\ - module\x18\x03\x20\x01(\tR\nrustModule\x12#\n\rcargo_feature\x18\x04\x20\ - \x01(\tR\x0ccargoFeature\"\xd4\x01\n\x0cFieldOptions\x12\x12\n\x04name\ - \x18\x01\x20\x01(\tR\x04name\x12\x16\n\x06ignore\x18\x02\x20\x01(\x08R\ - \x06ignore\x12\x20\n\x03acl\x18\x03\x20\x03(\x0b2\x0e.yara.AclEntryR\x03\ - acl\x12\x1c\n\tlowercase\x18\x04\x20\x01(\x08R\tlowercase\x12\x10\n\x03f\ - mt\x18\x05\x20\x01(\tR\x03fmt\x12F\n\x12deprecation_notice\x18\x06\x20\ - \x01(\x0b2\x17.yara.DeprecationNoticeR\x11deprecationNotice\"\x86\x01\n\ - \x08AclEntry\x12\x1f\n\x0berror_title\x18\x01\x20\x02(\tR\nerrorTitle\ - \x12\x1f\n\x0berror_label\x18\x02\x20\x02(\tR\nerrorLabel\x12\x1b\n\tacc\ - ept_if\x18\x03\x20\x03(\tR\x08acceptIf\x12\x1b\n\treject_if\x18\x04\x20\ - \x03(\tR\x08rejectIf\"]\n\x11DeprecationNotice\x12\x12\n\x04text\x18\x01\ - \x20\x02(\tR\x04text\x12\x12\n\x04help\x18\x02\x20\x01(\tR\x04help\x12\ - \x20\n\x0breplacement\x18\x03\x20\x01(\tR\x0breplacement\"$\n\x0eMessage\ - Options\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"9\n\x0bEnumOption\ - s\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x16\n\x06inline\x18\ - \x02\x20\x01(\x08R\x06inline\"C\n\x10EnumValueOptions\x12\x12\n\x03i64\ - \x18\x01\x20\x01(\x03H\0R\x03i64\x12\x12\n\x03f64\x18\x02\x20\x01(\x01H\ - \0R\x03f64B\x07\n\x05value:Z\n\x0emodule_options\x18\xaf\x92\x03\x20\x01\ - (\x0b2\x13.yara.ModuleOptions\x12\x1c.google.protobuf.FileOptionsR\rmodu\ - leOptions:X\n\rfield_options\x18\xb0\x92\x03\x20\x01(\x0b2\x12.yara.Fiel\ - dOptions\x12\x1d.google.protobuf.FieldOptionsR\x0cfieldOptions:`\n\x0fme\ - ssage_options\x18\xb1\x92\x03\x20\x01(\x0b2\x14.yara.MessageOptions\x12\ - \x1f.google.protobuf.MessageOptionsR\x0emessageOptions:T\n\x0cenum_optio\ - ns\x18\xb2\x92\x03\x20\x01(\x0b2\x11.yara.EnumOptions\x12\x1c.google.pro\ - tobuf.EnumOptionsR\x0benumOptions:Z\n\nenum_value\x18\xb3\x92\x03\x20\ - \x01(\x0b2\x16.yara.EnumValueOptions\x12!.google.protobuf.EnumValueOptio\ - nsR\tenumValueb\x06proto2\ + \n\nyara.proto\x12\x04yara\x1a\x20google/protobuf/descriptor.proto\"k\n\ + \rModuleOptions\x12\x12\n\x04name\x18\x01\x20\x02(\tR\x04name\x12!\n\x0c\ + root_message\x18\x02\x20\x02(\tR\x0brootMessage\x12#\n\rcargo_feature\ + \x18\x03\x20\x01(\tR\x0ccargoFeature\"\xd4\x01\n\x0cFieldOptions\x12\x12\ + \n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x16\n\x06ignore\x18\x02\x20\ + \x01(\x08R\x06ignore\x12\x20\n\x03acl\x18\x03\x20\x03(\x0b2\x0e.yara.Acl\ + EntryR\x03acl\x12\x1c\n\tlowercase\x18\x04\x20\x01(\x08R\tlowercase\x12\ + \x10\n\x03fmt\x18\x05\x20\x01(\tR\x03fmt\x12F\n\x12deprecation_notice\ + \x18\x06\x20\x01(\x0b2\x17.yara.DeprecationNoticeR\x11deprecationNotice\ + \"\x86\x01\n\x08AclEntry\x12\x1f\n\x0berror_title\x18\x01\x20\x02(\tR\ne\ + rrorTitle\x12\x1f\n\x0berror_label\x18\x02\x20\x02(\tR\nerrorLabel\x12\ + \x1b\n\taccept_if\x18\x03\x20\x03(\tR\x08acceptIf\x12\x1b\n\treject_if\ + \x18\x04\x20\x03(\tR\x08rejectIf\"]\n\x11DeprecationNotice\x12\x12\n\x04\ + text\x18\x01\x20\x02(\tR\x04text\x12\x12\n\x04help\x18\x02\x20\x01(\tR\ + \x04help\x12\x20\n\x0breplacement\x18\x03\x20\x01(\tR\x0breplacement\"$\ + \n\x0eMessageOptions\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"9\n\ + \x0bEnumOptions\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x16\n\ + \x06inline\x18\x02\x20\x01(\x08R\x06inline\"C\n\x10EnumValueOptions\x12\ + \x12\n\x03i64\x18\x01\x20\x01(\x03H\0R\x03i64\x12\x12\n\x03f64\x18\x02\ + \x20\x01(\x01H\0R\x03f64B\x07\n\x05value:Z\n\x0emodule_options\x18\xaf\ + \x92\x03\x20\x01(\x0b2\x13.yara.ModuleOptions\x12\x1c.google.protobuf.Fi\ + leOptionsR\rmoduleOptions:X\n\rfield_options\x18\xb0\x92\x03\x20\x01(\ + \x0b2\x12.yara.FieldOptions\x12\x1d.google.protobuf.FieldOptionsR\x0cfie\ + ldOptions:`\n\x0fmessage_options\x18\xb1\x92\x03\x20\x01(\x0b2\x14.yara.\ + MessageOptions\x12\x1f.google.protobuf.MessageOptionsR\x0emessageOptions\ + :T\n\x0cenum_options\x18\xb2\x92\x03\x20\x01(\x0b2\x11.yara.EnumOptions\ + \x12\x1c.google.protobuf.EnumOptionsR\x0benumOptions:Z\n\nenum_value\x18\ + \xb3\x92\x03\x20\x01(\x0b2\x16.yara.EnumValueOptions\x12!.google.protobu\ + f.EnumValueOptionsR\tenumValueb\x06proto2\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/lib/src/modules/protos/hash.proto b/lib/src/modules/protos/hash.proto index 888b435a7..fc77eaba4 100644 --- a/lib/src/modules/protos/hash.proto +++ b/lib/src/modules/protos/hash.proto @@ -6,7 +6,6 @@ package hash; option (yara.module_options) = { name : "hash" root_message: "hash.Hash" - rust_module: "hash" cargo_feature: "hash-module" }; diff --git a/lib/src/modules/protos/lnk.proto b/lib/src/modules/protos/lnk.proto index df4305bff..ff025570f 100644 --- a/lib/src/modules/protos/lnk.proto +++ b/lib/src/modules/protos/lnk.proto @@ -6,7 +6,6 @@ package lnk; option (yara.module_options) = { name : "lnk" root_message: "lnk.Lnk" - rust_module: "lnk" cargo_feature: "lnk-module" }; diff --git a/lib/src/modules/protos/macho.proto b/lib/src/modules/protos/macho.proto index d7b56a4f6..556885d5c 100644 --- a/lib/src/modules/protos/macho.proto +++ b/lib/src/modules/protos/macho.proto @@ -6,7 +6,6 @@ package macho; option (yara.module_options) = { name : "macho" root_message: "macho.Macho" - rust_module: "macho" cargo_feature: "macho-module" }; diff --git a/lib/src/modules/protos/magic.proto b/lib/src/modules/protos/magic.proto index 50b2cb6df..9ef9c804e 100644 --- a/lib/src/modules/protos/magic.proto +++ b/lib/src/modules/protos/magic.proto @@ -7,7 +7,6 @@ package magic; option (yara.module_options) = { name : "magic" root_message: "magic.Magic" - rust_module: "magic" cargo_feature: "magic-module" }; diff --git a/lib/src/modules/protos/math.proto b/lib/src/modules/protos/math.proto index 3b8daa74e..492120927 100644 --- a/lib/src/modules/protos/math.proto +++ b/lib/src/modules/protos/math.proto @@ -6,7 +6,6 @@ package math; option (yara.module_options) = { name : "math" root_message: "math.Math" - rust_module: "math" cargo_feature: "math-module" }; diff --git a/lib/src/modules/protos/pe.proto b/lib/src/modules/protos/pe.proto index b9dd5681e..cc5e40421 100644 --- a/lib/src/modules/protos/pe.proto +++ b/lib/src/modules/protos/pe.proto @@ -7,7 +7,6 @@ package pe; option (yara.module_options) = { name : "pe" root_message: "pe.PE" - rust_module: "pe" cargo_feature: "pe-module" }; diff --git a/lib/src/modules/protos/string.proto b/lib/src/modules/protos/string.proto index 286b44410..20209b7e6 100644 --- a/lib/src/modules/protos/string.proto +++ b/lib/src/modules/protos/string.proto @@ -6,7 +6,6 @@ package string; option (yara.module_options) = { name : "string" root_message: "string.String" - rust_module: "string" cargo_feature: "string-module" }; diff --git a/lib/src/modules/protos/test_proto2.proto b/lib/src/modules/protos/test_proto2.proto index 2199f408e..edf613747 100644 --- a/lib/src/modules/protos/test_proto2.proto +++ b/lib/src/modules/protos/test_proto2.proto @@ -34,18 +34,6 @@ option (yara.module_options) = { // the "test_proto2." prefix comes after the package name. root_message: "test_proto2.TestProto2" - // The name of the Rust module that contains the code for this module. A - // module with this name must exists under src/modules. In this case the - // module name is "test_proto2", we can create a module with that name in - // two ways: by creating a file "test_proto2.rs" under src/modules, or by - // creating a "test_proto2" directory under src/modules and putting a - // "mod.rs" file inside of it. - // - // Notice however that this is optional, as YARA modules can consists only - // in the data structure defined by this proto file, and don't need to have - // any associated code. - rust_module: "test_proto2" - // The name of the feature that controls whether this module is compiled or // not. A feature with this name must be added to the Cargo.toml file. cargo_feature: "test_proto2-module" diff --git a/lib/src/modules/protos/test_proto3.proto b/lib/src/modules/protos/test_proto3.proto index fdd214d4d..fac1cbe47 100644 --- a/lib/src/modules/protos/test_proto3.proto +++ b/lib/src/modules/protos/test_proto3.proto @@ -34,18 +34,6 @@ option (yara.module_options) = { // "test_proto2." prefix comes after the package name. root_message: "test_proto3.TestProto3" - // The name of the Rust module that contains the code for this module. A - // module with this name must exists under src/modules. In this case the - // module name is "test_proto3", we can create a module with that name in - // two ways: by creating a file "test_proto3.rs" under src/modules, or by - // creating a "test_proto3" directory under src/modules and putting a - // "mod.rs" file inside of it. - // - // Notice however that this is optional, as YARA modules can consists only - // in the data structure defined by this proto file, and don't need to have - // any associated code. - rust_module: "test_proto3" - // The name of the feature that controls whether this module is compiled or // not. A feature with this name must be added to the Cargo.toml file. cargo_feature: "test_proto3-module" diff --git a/lib/src/modules/protos/time.proto b/lib/src/modules/protos/time.proto index 79351d4cd..94ffd9f40 100644 --- a/lib/src/modules/protos/time.proto +++ b/lib/src/modules/protos/time.proto @@ -6,7 +6,6 @@ package time; option (yara.module_options) = { name : "time" root_message: "time.Time" - rust_module: "time" cargo_feature: "time-module" }; diff --git a/lib/src/modules/protos/vt/titan.proto b/lib/src/modules/protos/vt/titan.proto index 979846314..50b8c3448 100644 --- a/lib/src/modules/protos/vt/titan.proto +++ b/lib/src/modules/protos/vt/titan.proto @@ -16,7 +16,6 @@ import "yara.proto"; option (yara.module_options) = { name: "vt" root_message: "vt.titan.LiveHuntData" - rust_module: "vt" cargo_feature: "vt-module" }; diff --git a/lib/src/modules/protos/yara.proto b/lib/src/modules/protos/yara.proto index daf9d59a1..0519f5473 100644 --- a/lib/src/modules/protos/yara.proto +++ b/lib/src/modules/protos/yara.proto @@ -10,8 +10,7 @@ import "google/protobuf/descriptor.proto"; message ModuleOptions { required string name = 1; required string root_message = 2; - optional string rust_module = 3; - optional string cargo_feature = 4; + optional string cargo_feature = 3; } message FieldOptions { diff --git a/lib/src/modules/string.rs b/lib/src/modules/string.rs index 3a76a0a8c..9ae287d6f 100644 --- a/lib/src/modules/string.rs +++ b/lib/src/modules/string.rs @@ -1,8 +1,6 @@ -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::string::*; - -#[module_main] fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { // Nothing to do, but we have to return our protobuf Ok(String::new()) @@ -104,3 +102,5 @@ mod tests { ); } } + +register_module!("string", String, main); diff --git a/lib/src/modules/test_proto2/mod.rs b/lib/src/modules/test_proto2/mod.rs index 7be984fba..5383f57be 100644 --- a/lib/src/modules/test_proto2/mod.rs +++ b/lib/src/modules/test_proto2/mod.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::test_proto2::NestedProto2; use crate::modules::protos::test_proto2::TestProto2; use crate::types::Struct; @@ -95,7 +95,6 @@ fn to_int(ctx: &ScanContext, string: RuntimeString) -> Option { string.parse::().ok() } -#[module_main] fn main(data: &[u8], meta: Option<&[u8]>) -> Result { let mut test = TestProto2::new(); @@ -192,3 +191,5 @@ fn main(data: &[u8], meta: Option<&[u8]>) -> Result { Ok(test) } + +register_module!("test_proto2", TestProto2, main); diff --git a/lib/src/modules/test_proto3/mod.rs b/lib/src/modules/test_proto3/mod.rs index ee699ad32..2cbb3e4bc 100644 --- a/lib/src/modules/test_proto3/mod.rs +++ b/lib/src/modules/test_proto3/mod.rs @@ -1,8 +1,10 @@ -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::test_proto3::TestProto3; -#[module_main] -fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { +fn main( + _data: &[u8], + _meta: Option<&[u8]>, +) -> Result { let mut test = TestProto3::new(); test.int32_zero = 0; @@ -37,3 +39,5 @@ fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { Ok(test) } + +register_module!("test_proto3", TestProto3, main); diff --git a/lib/src/modules/time.rs b/lib/src/modules/time.rs index 68e32f8be..4ce5eeca1 100644 --- a/lib/src/modules/time.rs +++ b/lib/src/modules/time.rs @@ -1,7 +1,6 @@ -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::time::*; -#[module_main] fn main(_data: &[u8], _meta: Option<&[u8]>) -> Result { // Nothing to do, but we have to return our protobuf Ok(Time::new()) @@ -42,3 +41,5 @@ mod tests { ); } } + +register_module!("time", Time, main); diff --git a/lib/src/modules/vt/mod.rs b/lib/src/modules/vt/mod.rs index 298c69af3..4e1197f5a 100644 --- a/lib/src/modules/vt/mod.rs +++ b/lib/src/modules/vt/mod.rs @@ -18,7 +18,7 @@ use bstr::BStr; use ipnet::IpNet; use protobuf::EnumFull; -use crate::modules::prelude::*; +use crate::mods::prelude::*; use crate::modules::protos::titan::*; use crate::modules::protos::vtnet::enriched_domain::Permutation; use crate::modules::vt::bitsquatting::bitsquatting; @@ -49,7 +49,6 @@ static SUBDOMAIN: LazyLock = LazyLock::new(|| { Struct::enum_value_i64(&Permutation::SUBDOMAIN.descriptor()).unwrap() }); -#[module_main] fn main( _data: &[u8], _meta: Option<&[u8]>, @@ -90,7 +89,7 @@ fn all_permutations( permutations(ctx, domain, target, 0x1F) } -/// Returns true if the domain is a permutation of the given `target` domain, +/// Returns true if the domain is a permutation of the given `target` domain, /// but the permutation must be any of the kinds specified in `permutation_kinds`. #[module_export(name = "permutation_of", method_of = "vt.net.EnrichedDomain")] fn permutations( @@ -159,9 +158,10 @@ fn permutations( if SUBDOMAIN.bitand(&permutation_kinds) != 0 && let (Some(legit), Some(scanned)) = (legit_prefix, scanned_prefix) - && interleaved(legit, scanned, '.') { - return true; - } + && interleaved(legit, scanned, '.') + { + return true; + } if HYPHENATION.bitand(&permutation_kinds) != 0 && interleaved(legit_domain, scanned_domain, '-') @@ -250,7 +250,7 @@ pub struct DomainParts<'a> { #[cfg(test)] mod tests { use crate::modules::protos::titan::LiveHuntData; - use crate::modules::vt::{parse_domain, DomainParts}; + use crate::modules::vt::{DomainParts, parse_domain}; use crate::{Compiler, Scanner}; use bstr::BStr; use protobuf::text_format::parse_from_str; @@ -530,3 +530,5 @@ mod tests { assert!(!squatting!("www.google.com", "www.goore.com")); } } + +register_module!("vt", LiveHuntData, main); diff --git a/lib/src/scanner/context.rs b/lib/src/scanner/context.rs index 13e68be18..d41ea17d6 100644 --- a/lib/src/scanner/context.rs +++ b/lib/src/scanner/context.rs @@ -90,67 +90,68 @@ impl WasmState { } /// Structure that holds information about the current scan. -pub(crate) struct ScanContext<'r, 'd> { +pub struct ScanContext<'r, 'd> { /// WASM state. - pub wasm: WasmState, + pub(crate) wasm: WasmState, /// Map where keys are object handles and values are objects used during /// the evaluation of rule conditions. Handles are opaque integer values /// that can be passed to and received from WASM code. Each handle identify /// an object (string, struct, array or map). - pub runtime_objects: IndexMap, + pub(crate) runtime_objects: IndexMap, /// The time that can be spent in a scan operation, including the /// execution of the rule conditions. - pub scan_timeout: Option, + pub(crate) scan_timeout: Option, /// The number of bytes at the left and right of the matching data /// that is stored to provide additional context about where the match /// was found. - pub match_context_size: usize, + pub(crate) match_context_size: usize, /// The current state of the scanner. - pub scan_state: ScanState<'d>, + pub(crate) scan_state: ScanState<'d>, /// Vector containing the IDs of the rules that matched, including both /// global and non-global ones. The rules are added first to the /// `matching_rules_per_ns` map, and then moved to this vector /// once the scan finishes. - pub matching_rules: Vec, + pub(crate) matching_rules: Vec, /// Map containing the IDs of rules that matched. Using an `IndexMap` /// because we want to keep the insertion order, so that rules in /// namespaces that were declared first, appear first in scan results. - pub matching_rules_per_ns: IndexMap>, + pub(crate) matching_rules_per_ns: IndexMap>, /// Number of private rules that have matched. This will be equal to or /// less than the length of `matching_rules`. - pub num_matching_private_rules: usize, + pub(crate) num_matching_private_rules: usize, /// Number of private rules that did not match. - pub num_non_matching_private_rules: usize, + pub(crate) num_non_matching_private_rules: usize, /// Compiled rules for this scan. - pub compiled_rules: &'r Rules, + pub(crate) compiled_rules: &'r Rules, /// Structure that contains top-level symbols, like module names /// and external variables. Symbols are normally looked up in this /// structure, except if `current_struct` is set to some other /// structure that overrides `root_struct`. - pub root_struct: Struct, + pub(crate) root_struct: Struct, /// Currently active structure that overrides the `root_struct` if /// set. - pub current_struct: Option>, + pub(crate) current_struct: Option>, /// Hash map that contains the protobuf messages returned by YARA modules. /// Keys are the fully qualified protobuf message name, and values are /// the message returned by the main function of the corresponding module. - pub module_outputs: FxHashMap>, + pub(crate) module_outputs: FxHashMap>, /// Hash map that contains the protobuf messages that has been explicitly /// provided by the user to be used as module outputs during the next scan /// operation. Keys are the fully qualified protobuf message names, and /// values are the protobuf messages set with [`Scanner::set_module_output`]. - pub user_provided_module_outputs: FxHashMap>, + pub(crate) user_provided_module_outputs: + FxHashMap>, /// Match tracker structure that holds unconfirmed and confirmed matches. - pub tracker: MatchTracker<'r>, + pub(crate) tracker: MatchTracker<'r>, /// When [`HEARTBEAT_COUNTER`] is larger than this value, the scan is /// aborted due to a timeout. - pub deadline: u64, + pub(crate) deadline: u64, /// Hash map that serves as a cache for regexps used in expressions like /// `some_var matches /foobar/`. Compiling a regexp is an expensive /// operation. Instead of compiling the regexp each time the expression /// is evaluated, it is compiled the first time and stored in this hash /// map. - pub regex_cache: RefCell>, + pub(crate) regex_cache: RefCell>, /// Persistent cache for grouped `RegexSet` automata. /// /// Like individual regular expressions, compiling a multi-pattern @@ -158,34 +159,35 @@ pub(crate) struct ScanContext<'r, 'd> { /// automata lazily upon the very first match request and preserves the /// compiled automata across all subsequent scans performed by the /// scanner instance. - pub regex_set_cache: + pub(crate) regex_set_cache: RefCell>, /// Engines for custom base64 alphabets used by base64 string modifiers. /// /// These engines are derived from rule literals and reused across scans. - pub custom_base64_engine_cache: Vec<(u32, base64::engine::GeneralPurpose)>, + pub(crate) custom_base64_engine_cache: + Vec<(u32, base64::engine::GeneralPurpose)>, /// Callback invoked every time a YARA rule calls `console.log`. - pub console_log: Option>, + pub(crate) console_log: Option>, /// Virtual Machines used for executing regexps. - pub vm: VM<'r>, + pub(crate) vm: VM<'r>, /// Hash map that tracks the time spend on each pattern. Keys are pattern /// PatternIds and values are the cumulative time spent on verifying each /// pattern. #[cfg(feature = "rules-profiling")] - pub time_spent_in_pattern: FxHashMap, + pub(crate) time_spent_in_pattern: FxHashMap, /// Time spent evaluating each rule. This vector has one entry per rule, /// which is the number of nanoseconds spent evaluating the rule. #[cfg(feature = "rules-profiling")] - pub time_spent_in_rule: Vec, + pub(crate) time_spent_in_rule: Vec, /// The time at which the evaluation of the current rule started. #[cfg(feature = "rules-profiling")] - pub rule_execution_start_time: u64, + pub(crate) rule_execution_start_time: u64, /// The ID of the last rule whose condition was executed. #[cfg(feature = "rules-profiling")] - pub last_executed_rule: Option, + pub(crate) last_executed_rule: Option, /// Clock used for measuring the time spend on each pattern. #[cfg(any(feature = "rules-profiling", feature = "logging"))] - pub clock: quanta::Clock, + pub(crate) clock: quanta::Clock, } #[cfg(feature = "rules-profiling")] @@ -194,7 +196,7 @@ impl ScanContext<'_, '_> { /// /// Profiling has an accumulative effect. When the scanner is used for /// scanning multiple files the times add up. - pub fn slowest_rules(&self, n: usize) -> Vec> { + pub(crate) fn slowest_rules(&self, n: usize) -> Vec> { debug_assert_eq!( self.compiled_rules.num_rules(), self.time_spent_in_rule.len() @@ -254,7 +256,7 @@ impl ScanContext<'_, '_> { } /// Clears profiling information. - pub fn clear_profiling_data(&mut self) { + pub(crate) fn clear_profiling_data(&mut self) { self.time_spent_in_rule.fill(0); self.time_spent_in_pattern.clear(); } @@ -338,7 +340,7 @@ impl ScanContext<'_, '_> { } /// Sets the value of a global variable. - pub fn set_global>( + pub(crate) fn set_global>( &mut self, ident: &str, value: T, diff --git a/lib/src/scanner/mod.rs b/lib/src/scanner/mod.rs index f49b7cdc8..63f56d539 100644 --- a/lib/src/scanner/mod.rs +++ b/lib/src/scanner/mod.rs @@ -2,7 +2,7 @@ The scanner takes the rules produces by the compiler and scans data with them. */ -use std::collections::{BTreeMap, HashMap, hash_map}; +use std::collections::{BTreeMap, HashMap}; use std::fmt::{Debug, Formatter}; use std::fs; use std::io::Read; @@ -22,21 +22,20 @@ use memmap2::{Mmap, MmapOptions}; use protobuf::{CodedInputStream, MessageDyn}; use thiserror::Error; +use crate::Variable; use crate::compiler::{RuleId, Rules}; use crate::models::Rule; -use crate::modules::{BUILTIN_MODULES, Module, ModuleError}; -use crate::scanner::context::create_wasm_store_and_ctx; -use crate::types::{Struct, TypeValue}; -use crate::variables::VariableError; -use crate::wasm::MATCHING_RULES_BITMAP_BASE; -use crate::wasm::runtime::Store; -use crate::{Variable, modules}; - +use crate::modules::{ModuleError, RegisteredModule}; pub(crate) use crate::scanner::context::RuntimeObject; pub(crate) use crate::scanner::context::RuntimeObjectHandle; pub(crate) use crate::scanner::context::ScanContext; pub(crate) use crate::scanner::context::ScanState; +use crate::scanner::context::create_wasm_store_and_ctx; pub(crate) use crate::scanner::matches::Match; +use crate::types::{Struct, TypeValue}; +use crate::variables::VariableError; +use crate::wasm::MATCHING_RULES_BITMAP_BASE; +use crate::wasm::runtime::Store; mod context; mod matches; @@ -403,9 +402,8 @@ impl<'r> Scanner<'r> { // Check if the protobuf message passed to this function corresponds // with any of the existing modules. - if !BUILTIN_MODULES - .iter() - .any(|m| m.1.root_struct_descriptor.full_name() == full_name) + if !crate::modules::registered_modules() + .any(|m| m.root_descriptor().full_name() == full_name) { return Err(ScanError::UnknownModule { module: full_name.to_string(), @@ -433,17 +431,24 @@ impl<'r> Scanner<'r> { // Try to find the module by name first, if not found, then try // to find a module where the fully-qualified name for its protobuf // message matches the `name` arguments. - let descriptor = if let Some(module) = BUILTIN_MODULES.get(name) { - Some(&module.root_struct_descriptor) - } else { - BUILTIN_MODULES.values().find_map(|module| { - if module.root_struct_descriptor.full_name() == name { - Some(&module.root_struct_descriptor) + let descriptor = crate::modules::registered_modules() + .find_map(|module| { + if module.name() == name { + Some(module.root_descriptor()) } else { None } }) - }; + .or_else(|| { + crate::modules::registered_modules().find_map(|module| { + let descriptor = module.root_descriptor(); + if descriptor.full_name() == name { + Some(descriptor) + } else { + None + } + }) + }); if descriptor.is_none() { return Err(ScanError::UnknownModule { module: name.to_string() }); @@ -563,12 +568,13 @@ impl<'r> Scanner<'r> { ctx.scan_state = ScanState::ScanningData(data); for module_name in ctx.compiled_rules.imports() { - // Lookup the module in the list of built-in modules. - let module = modules::BUILTIN_MODULES - .get(module_name) + // Look up the module in the module registry. + let module = crate::modules::registered_modules() + .find(|module| module.name() == module_name) .unwrap_or_else(|| panic!("module `{module_name}` not found")); - let root_struct_name = module.root_struct_descriptor.full_name(); + let module_root_descriptor = module.root_descriptor(); + let root_struct_name = module_root_descriptor.full_name(); let module_output; // If the user already provided some output for the module by @@ -585,15 +591,15 @@ impl<'r> Scanner<'r> { options.module_metadata.get(module_name).copied() }); - if let Some(main_fn) = module.main_fn { - module_output = Some( - main_fn(ctx.scanned_data().unwrap(), meta).map_err( - |err| ScanError::ModuleError { - module: module_name.to_string(), - err, - }, - )?, - ); + if let Some(main_res) = + module.main_fn(ctx.scanned_data().unwrap(), meta) + { + module_output = Some(main_res.map_err(|err| { + ScanError::ModuleError { + module: module_name.to_string(), + err, + } + })?); } else { module_output = None; } @@ -604,10 +610,10 @@ impl<'r> Scanner<'r> { // the expected type. debug_assert_eq!( module_output.descriptor_dyn().full_name(), - module.root_struct_descriptor.full_name(), + root_struct_name, "main function of module `{}` must return `{}`, but returned `{}`", module_name, - module.root_struct_descriptor.full_name(), + root_struct_name, module_output.descriptor_dyn().full_name(), ); @@ -619,7 +625,7 @@ impl<'r> Scanner<'r> { module_output.is_initialized_dyn(), "module `{}` returned a protobuf `{}` where some required fields are not initialized ", module_name, - module.root_struct_descriptor.full_name() + root_struct_name ); } @@ -638,7 +644,7 @@ impl<'r> Scanner<'r> { !cfg!(feature = "constant-folding"); let module_struct = Struct::from_proto_descriptor_and_msg( - &module.root_struct_descriptor, + &module_root_descriptor, module_output.as_deref(), generate_fields_for_enums, ); @@ -806,11 +812,18 @@ impl<'a, 'r> ScanResults<'a, 'r> { &self, module_name: &str, ) -> Option<&'a dyn MessageDyn> { - let module = BUILTIN_MODULES.get(module_name)?; + let module_descriptor = crate::modules::registered_modules() + .find_map(|m| { + if m.name() == module_name { + Some(m.root_descriptor()) + } else { + None + } + })?; let module_output = self .ctx .module_outputs - .get(module.root_struct_descriptor.full_name())? + .get(module_descriptor.full_name())? .as_ref(); Some(module_output) } @@ -983,7 +996,7 @@ impl ExactSizeIterator for NonMatchingRules<'_, '_> { pub struct ModuleOutputs<'a, 'r> { ctx: &'a ScanContext<'r, 'a>, len: usize, - iterator: hash_map::Iter<'a, &'a str, Module>, + iterator: Box + 'a>, } impl<'a, 'r> ModuleOutputs<'a, 'r> { @@ -991,7 +1004,7 @@ impl<'a, 'r> ModuleOutputs<'a, 'r> { Self { ctx, len: ctx.module_outputs.len(), - iterator: BUILTIN_MODULES.iter(), + iterator: Box::new(crate::modules::registered_modules()), } } } @@ -1008,13 +1021,13 @@ impl<'a> Iterator for ModuleOutputs<'a, '_> { fn next(&mut self) -> Option { loop { - let (name, module) = self.iterator.next()?; + let module = self.iterator.next()?; if let Some(module_output) = self .ctx .module_outputs - .get(module.root_struct_descriptor.full_name()) + .get(module.root_descriptor().full_name()) { - return Some((*name, module_output.as_ref())); + return Some((module.name(), module_output.as_ref())); } } } diff --git a/lib/src/types/structure.rs b/lib/src/types/structure.rs index 4f997c71f..9fb9d3d94 100644 --- a/lib/src/types/structure.rs +++ b/lib/src/types/structure.rs @@ -2,6 +2,15 @@ use std::iter; use std::ops::Deref; use std::rc::Rc; +use crate::modules::RegisteredModule; +use crate::modules::protos::yara as protos; +use crate::modules::protos::yara::enum_value_options::Value as EnumValue; +use crate::modules::protos::yara::exts::{ + enum_options, enum_value, field_options, message_options, module_options, +}; +use crate::symbols::{Symbol, SymbolLookup}; +use crate::types::{Array, Map, StringConstraint, TypeValue}; +use crate::wasm::WasmExport; use bstr::BString; use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; @@ -13,16 +22,6 @@ use protobuf::reflect::{EnumValueDescriptor, Syntax}; use protobuf::{MessageDyn, MessageField}; use serde::{Deserialize, Serialize}; -use crate::modules::Module; -use crate::modules::protos::yara as protos; -use crate::modules::protos::yara::enum_value_options::Value as EnumValue; -use crate::modules::protos::yara::exts::{ - enum_options, enum_value, field_options, message_options, module_options, -}; -use crate::symbols::{Symbol, SymbolLookup}; -use crate::types::{Array, Map, StringConstraint, TypeValue}; -use crate::wasm::WasmExport; - /// Each of the entries in an Access Control List (ACL) /// /// When defining the structure of a module in a `.proto` file, you can specify @@ -1219,12 +1218,12 @@ impl PartialEq for Struct { } } -impl From<&Module> for Rc { - /// Creates a `Rc` from a [`Module`] definition. - fn from(module: &Module) -> Self { +impl From<&dyn RegisteredModule> for Rc { + /// Creates a `Rc` from a [`RegisteredModule`] definition. + fn from(module: &dyn RegisteredModule) -> Self { // Create the structure that describes the module. let mut module_struct = Struct::from_proto_descriptor_and_msg( - &module.root_struct_descriptor, + &module.root_descriptor(), None, true, ); @@ -1237,7 +1236,7 @@ impl From<&Module> for Rc { // If the YARA module has an associated Rust module, check if it // exports some function and add it to the structure. - if let Some(rust_module_name) = module.rust_module_name { + if let Some(rust_module_name) = module.rust_module_name() { let functions = WasmExport::get_functions(|export| { export.public && export.rust_module_path.ends_with(rust_module_name) diff --git a/lib/src/wasm/mod.rs b/lib/src/wasm/mod.rs index 1d505c88c..3a71b2e49 100644 --- a/lib/src/wasm/mod.rs +++ b/lib/src/wasm/mod.rs @@ -90,7 +90,6 @@ use smallvec::{SmallVec, smallvec}; use yara_x_macros::wasm_export; use crate::compiler::{LiteralId, PatternId, RegexId, RuleId}; -use crate::modules::BUILTIN_MODULES; use crate::scanner::{RuntimeObjectHandle, ScanContext}; use crate::types::{ Array, Func, FuncSignature, Map, Struct, TypeValue, Value, @@ -137,8 +136,8 @@ pub(crate) fn wasm_exports() -> impl Iterator { inventory::iter::() } -/// Type of each entry in [`WASM_EXPORTS`]. -pub(crate) struct WasmExport { +/// Describes a function that is exported to WASM code. +pub struct WasmExport { /// Function's name. pub name: &'static str, /// Function's mangled name. The mangled name contains information about @@ -170,15 +169,15 @@ impl WasmExport { /// /// The fully qualified name includes not only the function's name, but /// also the module's name (e.g: `my_module.my_struct.my_func@ii@i`) - pub fn fully_qualified_mangled_name(&self) -> String { + pub(crate) fn fully_qualified_mangled_name(&self) -> String { if self.method_of.is_some() { return self.mangled_name.to_string(); } - for (module_name, module) in BUILTIN_MODULES.iter() { - if let Some(rust_module_name) = module.rust_module_name + for module in crate::modules::registered_modules() { + if let Some(rust_module_name) = module.rust_module_name() && self.rust_module_path.contains(rust_module_name) { - return format!("{}.{}", module_name, self.mangled_name); + return format!("{}.{}", module.name(), self.mangled_name); } } self.mangled_name.to_owned() @@ -196,7 +195,9 @@ impl WasmExport { /// Keys are function names and values are [`Func`] structures. Overloaded /// functions appear in the map as a single entry where the [`Func`] has /// multiple signatures. - pub fn get_functions

(predicate: P) -> FxHashMap<&'static str, Func> + pub(crate) fn get_functions

( + predicate: P, + ) -> FxHashMap<&'static str, Func> where P: FnMut(&&WasmExport) -> bool, { @@ -246,7 +247,9 @@ impl WasmExport { /// #[module_export(method_of = "my_module.MyStructure")] /// fn some_method(...) { ... } /// ``` - pub fn get_methods(type_name: &str) -> FxHashMap<&'static str, Func> { + pub(crate) fn get_methods( + type_name: &str, + ) -> FxHashMap<&'static str, Func> { WasmExport::get_functions(|export| { export.method_of.is_some_and(|name| name == type_name) }) @@ -258,7 +261,7 @@ impl WasmExport { /// Implementors of this trait are [`WasmExportedFn0`], [`WasmExportedFn1`], /// [`WasmExportedFn2`], etc. Each of these types is a generic type that /// represents all functions with 0, 1, and 2 arguments respectively. -pub(crate) trait WasmExportedFn { +pub trait WasmExportedFn { /// Returns the function that will be passed to the selected runtime linker /// while linking the WASM code to this function. fn trampoline(&'static self) -> Trampoline>; @@ -572,7 +575,7 @@ where } } -pub fn wasmtime_to_walrus(ty: &ValType) -> walrus::ValType { +fn wasmtime_to_walrus(ty: &ValType) -> walrus::ValType { #[allow(unreachable_patterns)] match ty { ValType::I64 => walrus::ValType::I64, @@ -627,7 +630,8 @@ fn type_id_to_wasmtime( macro_rules! impl_wasm_exported_fn { ($name:ident $($args:ident)*) => { #[allow(dead_code)] - pub(super) struct $name <$($args,)* R> + #[allow(missing_docs)] + pub struct $name <$($args,)* R> where $($args: 'static,)* R: 'static, diff --git a/lib/src/wasm/runtime/browser.rs b/lib/src/wasm/runtime/browser.rs index 5e80d941a..658dd06e2 100644 --- a/lib/src/wasm/runtime/browser.rs +++ b/lib/src/wasm/runtime/browser.rs @@ -14,13 +14,13 @@ use super::common::{self, RuntimeBackend}; /// Browser runtime backend. #[derive(Clone, Default)] -pub(crate) struct Backend; +pub struct Backend; pub(crate) use super::common::{ AsContext, AsContextMut, Config, Engine, OptLevel, }; /// Alias for [`common::Caller`] specialized for the browser backend. -pub(crate) type Caller<'a, T> = common::Caller<'a, T, Backend>; +pub type Caller<'a, T> = common::Caller<'a, T, Backend>; /// Alias for [`common::Instance`] specialized for the browser backend. pub(crate) type Instance = common::Instance; /// Alias for [`common::Linker`] specialized for the browser backend. diff --git a/lib/src/wasm/runtime/common.rs b/lib/src/wasm/runtime/common.rs index 26f1a22fb..8faeb7ef1 100644 --- a/lib/src/wasm/runtime/common.rs +++ b/lib/src/wasm/runtime/common.rs @@ -254,11 +254,13 @@ impl AsContextMut for Pin>> { } /// View passed to host callbacks. -pub(crate) struct Caller<'a, T, B: RuntimeBackend> { +#[allow(private_bounds)] +pub struct Caller<'a, T, B: RuntimeBackend> { /// Store being used for the callback. pub(crate) store: &'a mut Store, } +#[allow(private_bounds)] impl<'a, T, B: RuntimeBackend> Caller<'a, T, B> { /// Creates a caller from a mutable store reference. pub(crate) fn new(store: &'a mut Store) -> Self { @@ -367,7 +369,7 @@ impl Engine { /// Value types supported by generated WASM code. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub(crate) enum ValType { +pub enum ValType { /// A 64-bit integer. I64, /// A 32-bit integer. @@ -380,7 +382,7 @@ pub(crate) enum ValType { /// Raw value passed across host callback trampolines. #[derive(Clone, Copy, Debug, Default)] -pub(crate) struct ValRaw(u64); +pub struct ValRaw(u64); impl ValRaw { /// Creates a raw value from an `i64`. diff --git a/lib/src/wasm/runtime/mod.rs b/lib/src/wasm/runtime/mod.rs index e94706fb3..80634f02e 100644 --- a/lib/src/wasm/runtime/mod.rs +++ b/lib/src/wasm/runtime/mod.rs @@ -15,7 +15,7 @@ mod native; mod browser; #[cfg(not(target_family = "wasm"))] -pub(crate) use native::*; +pub use native::*; #[cfg(target_family = "wasm")] -pub(crate) use browser::*; +pub use browser::*; diff --git a/lib/src/wasm/runtime/native.rs b/lib/src/wasm/runtime/native.rs index 4be78e3c0..a9152c2cb 100644 --- a/lib/src/wasm/runtime/native.rs +++ b/lib/src/wasm/runtime/native.rs @@ -6,9 +6,10 @@ use crate::errors::SerializationError; use anyhow::anyhow; use std::mem::transmute; +pub use wasmtime::Caller; /// Wasmtime types re-exported by the native runtime. pub(crate) use wasmtime::{ - AsContext, AsContextMut, Caller, Config, Engine, Extern, FuncType, Global, + AsContext, AsContextMut, Config, Engine, Extern, FuncType, Global, GlobalType, Instance, Memory, MemoryType, Module, Mutability, OptLevel, Store, TypedFunc, Val, ValRaw, ValType, }; diff --git a/lib/src/wasm/string.rs b/lib/src/wasm/string.rs index c05639467..ee6313715 100644 --- a/lib/src/wasm/string.rs +++ b/lib/src/wasm/string.rs @@ -8,12 +8,14 @@ use crate::scanner::{ use crate::utils::cast; /// This trait is implemented by [RuntimeString], [FixedLenString], [Lowercase] and [Uppercase]. -pub(crate) trait String: Default { +pub trait String: Default { /// Creates a new string. fn new>>(s: V) -> Self; /// Returns this string as a primitive type suitable to be passed to WASM. fn into_wasm_with_ctx(self, ctx: &mut ScanContext) -> RuntimeStringWasm; + + /// Returns a new string from a byte slice. fn from_slice(ctx: &ScanContext, s: &[u8]) -> Self; } @@ -69,13 +71,18 @@ pub(crate) type RuntimeStringWasm = i64; /// [`ScanContext`], and passes around only the handle that allows locating /// the string in that map. #[derive(Debug, PartialEq)] -pub(crate) enum RuntimeString { +pub enum RuntimeString { /// A literal string appearing in the source code. The string is identified /// by its [`LiteralId`] within the literal strings pool. Literal(LiteralId), /// A string found in the scanned data, represented by the offset within /// the data and its length. - ScannedDataSlice { offset: usize, length: usize }, + ScannedDataSlice { + /// String's offset in the scanned data. + offset: usize, + /// String's length. + length: usize, + }, /// A reference-counted string. Rc(Rc), } @@ -144,7 +151,7 @@ impl String for RuntimeString { impl RuntimeString { /// Returns this string as a &[`BStr`]. - pub(crate) fn as_bstr<'a>(&'a self, ctx: &'a ScanContext) -> &'a BStr { + pub fn as_bstr<'a>(&'a self, ctx: &'a ScanContext) -> &'a BStr { match self { Self::Literal(id) => { ctx.compiled_rules.lit_pool().get(*id).unwrap() @@ -161,7 +168,7 @@ impl RuntimeString { /// /// If the string is not valid UTF-8, then an error is returned. #[inline] - pub(crate) fn to_str<'a>( + pub fn to_str<'a>( &'a self, ctx: &'a ScanContext, ) -> Result<&'a str, Utf8Error> { @@ -371,7 +378,7 @@ fn ends_with_ascii_case_insensitive(haystack: &[u8], suffix: &[u8]) -> bool { /// Trying to create a [FixedLenString] with some length that is not the one /// specified by the `LEN` parameter will cause a panic. #[derive(Debug, Default)] -pub(crate) struct FixedLenString(RuntimeString); +pub struct FixedLenString(RuntimeString); impl String for FixedLenString { fn new>>(s: S) -> Self { @@ -403,8 +410,9 @@ impl String for FixedLenString { } } +/// Represents a string that is always lowercase. #[derive(Debug, Default)] -pub(crate) struct Lowercase(S); +pub struct Lowercase(S); impl String for Lowercase { fn new>>(s: V) -> Self { @@ -420,8 +428,9 @@ impl String for Lowercase { } } +/// Represents a string that is always uppercase. #[derive(Debug, Default)] -pub(crate) struct Uppercase(S); +pub struct Uppercase(S); impl String for Uppercase { fn new>>(s: V) -> Self { diff --git a/macros/src/lib.rs b/macros/src/lib.rs index e58303f95..ad9e8d690 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -4,7 +4,6 @@ use syn::{DeriveInput, Error, ItemFn, parse_macro_input}; mod error; mod module_export; -mod module_main; mod wasm_export; /// The `ErrorStruct` derive macro generates boilerplate code for structs that @@ -125,32 +124,6 @@ pub fn error_enum_macro_derive(input: TokenStream) -> TokenStream { .into() } -/// The `module_main` macro is used for indicating which is the main function -/// in a YARA module. -/// -/// The main function in a YARA module receives a slice that contains the -/// data being scanned, and must return the protobuf structure that corresponds -/// to the module. The function can have any name, as long as it is marked with -/// `#[module_main]`, but it's a good practice to name it `main`. -/// -/// # Example -/// -/// ```text -/// #[module_main] -/// fn main(data: &[u8]) -> SomeProto { -/// let some_proto = SomeProto::new(); -/// // ... fill some_proto with data ... -/// some_proto -/// } -/// ``` -#[proc_macro_attribute] -pub fn module_main(_attr: TokenStream, input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as ItemFn); - module_main::impl_module_main_macro(input) - .unwrap_or_else(Error::into_compile_error) - .into() -} - /// The `wasm_export` macro is used for declaring a Rust function that will be /// called from WASM. /// diff --git a/macros/src/module_export.rs b/macros/src/module_export.rs index bd168800d..0aa9050cc 100644 --- a/macros/src/module_export.rs +++ b/macros/src/module_export.rs @@ -62,9 +62,11 @@ pub(crate) fn impl_module_export_macro( // `&ScanContext` to `&mut Caller<'_, ScanContext>`. let mut fn_args: Punctuated = Punctuated::new(); - fn_args.push(syn::parse2(quote! { + let caller_arg = syn::parse2(quote! { caller: &mut Caller<'_, ScanContext> - })?); + })?; + + fn_args.push(caller_arg); fn_args.extend(func.sig.inputs.into_iter().skip(1)); @@ -85,6 +87,7 @@ pub(crate) fn impl_module_export_macro( let rust_fn_name = func.sig.ident; let fn_name = attr_args.name.unwrap_or(rust_fn_name.to_string()); let sync = attr_args.sync.unwrap_or_else(|| "none".to_owned()); + let method_of = attr_args.method_of; // Modify the original function and convert it into the thunk function. func.sig.ident = format_ident!("__thunk__{}", rust_fn_name); @@ -92,13 +95,15 @@ pub(crate) fn impl_module_export_macro( func.block = syn::parse2(quote! {{ #rust_fn_name(caller.data_mut(), #arg_pats) - }}) - .unwrap(); + }})?; - let wasm_export = if let Some(method_of) = attr_args.method_of { - quote! { #[wasm_export(name = #fn_name, public = true, method_of = #method_of, sync = #sync)] } - } else { - quote! { #[wasm_export(name = #fn_name, public = true, sync = #sync)] } + let wasm_export = match &method_of { + Some(m) => { + quote! { #[wasm_export(name = #fn_name, public = true, method_of = #m, sync = #sync)] } + } + None => { + quote! { #[wasm_export(name = #fn_name, public = true, sync = #sync)] } + } }; // Add the thunk function to the output. diff --git a/macros/src/module_main.rs b/macros/src/module_main.rs deleted file mode 100644 index a08e13953..000000000 --- a/macros/src/module_main.rs +++ /dev/null @@ -1,23 +0,0 @@ -extern crate proc_macro; - -use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use syn::{ItemFn, Result}; - -pub(crate) fn impl_module_main_macro(input: ItemFn) -> Result { - let fn_name = &input.sig.ident; - - let main_stub = quote! { - use protobuf::MessageDyn; - use crate::modules::ModuleError; - pub(crate) fn __main__(data: &[u8], meta: Option<&[u8]>) -> Result, ModuleError> { - #fn_name(data, meta).map(|ok| Box::new(ok) as Box) - } - }; - - let mut token_stream = input.to_token_stream(); - - token_stream.extend(main_stub); - - Ok(token_stream) -} diff --git a/macros/src/wasm_export.rs b/macros/src/wasm_export.rs index f6d4e66e5..1a9574ef9 100644 --- a/macros/src/wasm_export.rs +++ b/macros/src/wasm_export.rs @@ -277,14 +277,8 @@ fn sync_flags_literal( /// Implementation for the `#[wasm_export]` attribute macro. /// /// This attribute is used in functions that will be called from WASM. -/// For each function using this attribute adds an entry in a global -/// registry that tracks all the functions that may be called from WASM. -/// -/// Under the hood, this macro uses either the `linkme` or the `inventory` -/// crate for maintaining the global registry. In the first case, a -/// `WasmExport` is added to the global `WASM_EXPORTS` slice, while in -/// the second cases it uses the `inventory::submit!` for adding a -/// `WasmExport` struct to the inventory. +/// For each function using this attribute it registers the function in the +/// global `inventory` registry so that it can be discovered at runtime. /// /// # Example /// @@ -301,19 +295,6 @@ fn sync_flags_literal( /// The code generated will be: /// /// ```text -/// #[cfg_attr(not(feature = "inventory"), distributed_slice(WASM_EXPORTS))] -/// pub(crate) static export__add: WasmExport = WasmExport { -/// name: "add", -/// mangled_name: "add@ii@i", -/// public: false, -/// rust_module_path: "yara_x::modules::my_module", -/// method_of: None, -/// sync_flags: 3, -/// func: &WasmExportedFn2 { target_fn: &add }, -/// description: Some(Cow::Borrowed("This function adds two numbers.")), -/// }; -/// -/// #[cfg(feature = "inventory")] /// inventory::submit! { /// WasmExport { /// name: "add", diff --git a/proto-json/src/yara.proto b/proto-json/src/yara.proto index 32b0f9ccf..3f343c5d0 100644 --- a/proto-json/src/yara.proto +++ b/proto-json/src/yara.proto @@ -10,8 +10,7 @@ import "google/protobuf/descriptor.proto"; message ModuleOptions { required string name = 1; required string root_message = 2; - optional string rust_module = 3; - optional string cargo_feature = 4; + optional string cargo_feature = 3; } message FieldOptions { diff --git a/proto-yaml/src/yara.proto b/proto-yaml/src/yara.proto index 32b0f9ccf..3f343c5d0 100644 --- a/proto-yaml/src/yara.proto +++ b/proto-yaml/src/yara.proto @@ -10,8 +10,7 @@ import "google/protobuf/descriptor.proto"; message ModuleOptions { required string name = 1; required string root_message = 2; - optional string rust_module = 3; - optional string cargo_feature = 4; + optional string cargo_feature = 3; } message FieldOptions { diff --git a/proto/src/yara.proto b/proto/src/yara.proto index 32b0f9ccf..3f343c5d0 100644 --- a/proto/src/yara.proto +++ b/proto/src/yara.proto @@ -10,8 +10,7 @@ import "google/protobuf/descriptor.proto"; message ModuleOptions { required string name = 1; required string root_message = 2; - optional string rust_module = 3; - optional string cargo_feature = 4; + optional string cargo_feature = 3; } message FieldOptions {