Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 0 additions & 69 deletions .github/workflows/codeql.yml

This file was deleted.

10 changes: 10 additions & 0 deletions lib/src/compiler/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ impl InvalidWarningCode {
/// Error returned while serializing/deserializing compiled rules.
#[derive(Error, Debug)]
pub enum SerializationError {
/// The data being deserialized was created with an incompatible version
/// of YARA-X.
#[error("incompatible version, expected {expected} got {actual}")]
InvalidVersion {
/// The expected version.
expected: u32,
/// The actual version found in the file.
actual: u32,
},

/// The data being deserialized doesn't contain YARA-X serialized rules.
#[error("not a YARA-X compiled rules file")]
InvalidFormat,
Expand Down
34 changes: 29 additions & 5 deletions lib/src/compiler/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ use crate::re::{BckCodeLoc, FwdCodeLoc, RegexpAtom};
use crate::string_pool::{BStringPool, StringPool};
use crate::{re, types, wasm, Rule};

/// Magic bytes prepended to any binary file generated by YARA-X.
const MAGIC: &[u8] = b"YARA-X\0\0";

/// Version of the serialization format.
///
/// This version is incremented every time a change is made to the binary
/// format in a way that breaks backwards compatibility.
const SERIALIZATION_VERSION: u32 = 1;

/// A set of YARA rules in compiled form.
///
/// This is the result from [`crate::Compiler::build`].
Expand Down Expand Up @@ -169,19 +178,31 @@ impl Rules {
B: AsRef<[u8]>,
{
let bytes = bytes.as_ref();
let magic = b"YARA-X";
let version_offset = MAGIC.len();
let data_offset = version_offset + size_of::<u32>();

if bytes.len() < magic.len() || &bytes[0..magic.len()] != magic {
if bytes.len() < data_offset || &bytes[0..version_offset] != MAGIC {
return Err(SerializationError::InvalidFormat);
}

let version = u32::from_le_bytes(
bytes[version_offset..data_offset].try_into().unwrap(),
);

if version != SERIALIZATION_VERSION {
return Err(SerializationError::InvalidVersion {
expected: SERIALIZATION_VERSION,
actual: version,
});
}

#[cfg(feature = "logging")]
let start = Instant::now();

// Skip the magic and deserialize the remaining data.
// Skip the header and deserialize the remaining data.
let (mut rules, _len): (Self, usize) =
bincode::serde::decode_from_slice(
&bytes[magic.len()..],
&bytes[data_offset..],
bincode::config::standard(),
)?;

Expand Down Expand Up @@ -229,7 +250,10 @@ impl Rules {
let mut writer = BufWriter::new(writer);

// Write file header.
writer.write_all(b"YARA-X")?;
writer.write_all(MAGIC)?;

// Write version.
writer.write_all(&SERIALIZATION_VERSION.to_le_bytes())?;

bincode::serde::encode_into_std_write(
self,
Expand Down
25 changes: 25 additions & 0 deletions lib/src/compiler/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,34 @@ fn serialization() {

assert!(matches!(
Rules::deserialize(b"YARA-X").err().unwrap(),
SerializationError::InvalidFormat
));

// A valid file starts with `MAGIC` and a version number, but the rest of
// the content is invalid because it is too short. This must produce a
// `DecodeError`.
let mut data = Vec::new();
data.extend(b"YARA-X\0\0");
data.extend(1u32.to_le_bytes());
data.extend(b"foo");

assert!(matches!(
Rules::deserialize(&data).err().unwrap(),
SerializationError::DecodeError(_)
));

// This is a valid file, but with a version number that is not the current
// one. This must produce an `InvalidVersion` error.
let mut data = Vec::new();
data.extend(b"YARA-X\0\0");
data.extend(0u32.to_le_bytes());
data.extend(b"foo");

assert!(matches!(
Rules::deserialize(&data).err().unwrap(),
SerializationError::InvalidVersion { expected: _, actual: 0 }
));

let rules = compile(r#"rule test { strings: $a = "foo" condition: $a }"#)
.unwrap()
.serialize()
Expand Down
60 changes: 30 additions & 30 deletions site/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"no-console": 0,
"quotes": ["error", "single"],
"comma-dangle": [
"error",
{
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore"
}
]
}
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"no-console": 0,
"quotes": ["error", "single"],
"comma-dangle": [
"error",
{
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore"
}
]
}
}
68 changes: 34 additions & 34 deletions site/.stylelintrc.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
{
"extends": "stylelint-config-standard-scss",
"rules": {
"no-empty-source": null,
"scss/comment-no-empty": null,
"scss/at-extend-no-missing-placeholder": null,
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": [
"extend",
"at-root",
"debug",
"warn",
"error",
"if",
"else",
"for",
"each",
"while",
"mixin",
"include",
"content",
"return",
"function",
"tailwind",
"apply",
"responsive",
"variants",
"screen"
]
}
]
}
{
"extends": "stylelint-config-standard-scss",
"rules": {
"no-empty-source": null,
"scss/comment-no-empty": null,
"scss/at-extend-no-missing-placeholder": null,
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": [
"extend",
"at-root",
"debug",
"warn",
"error",
"if",
"else",
"for",
"each",
"while",
"mixin",
"include",
"content",
"return",
"function",
"tailwind",
"apply",
"responsive",
"variants",
"screen"
]
}
]
}
}
Loading