diff --git a/capi/include/yara_x.h b/capi/include/yara_x.h index 1dbe05b37..a44fcb56b 100644 --- a/capi/include/yara_x.h +++ b/capi/include/yara_x.h @@ -452,9 +452,9 @@ enum YRX_RESULT yrx_compiler_define_global_float(struct YRX_COMPILER *compiler, // (e.g., booleans, integers, strings), prefer dedicated functions to avoid // the overhead of JSON deserialization. // -// When defining a map, keys must be of string type, and values can be -// any of the types supported by YARA, including other maps. Arrays must be -// homogeneous (all elements must be the same type). +// When defining a map, keys must be of string type and valid YARA identifiers, +// and values can be any of the types supported by YARA, including other maps. +// Arrays must be homogeneous (all elements must be the same type). enum YRX_RESULT yrx_compiler_define_global_json(struct YRX_COMPILER *compiler, const char *ident, const char *value); diff --git a/lib/src/compiler/mod.rs b/lib/src/compiler/mod.rs index 70e4cda30..f048d0be7 100644 --- a/lib/src/compiler/mod.rs +++ b/lib/src/compiler/mod.rs @@ -646,6 +646,12 @@ impl<'a> Compiler<'a> { /// `i64`, `i32`, `i16`, `i8`, `u32`, `u16`, `u8`, `f64`, `f32`, `bool`, /// `&str`, `String` and [`serde_json::Value`]. /// + /// When using a [`serde_json::Value`] there are certain limitations: keys + /// in maps must be valid YARA identifiers (the first character must be `_` + /// or a letter, the remaining ones must be `_`, a letter or a digit), + /// because these maps are translated into YARA structures. Also, all items + /// in an array must have the same type. + /// /// ``` /// # use yara_x::Compiler; /// assert!(Compiler::new() diff --git a/lib/src/compiler/tests/mod.rs b/lib/src/compiler/tests/mod.rs index 191111790..05acf9ce9 100644 --- a/lib/src/compiler/tests/mod.rs +++ b/lib/src/compiler/tests/mod.rs @@ -523,10 +523,17 @@ fn globals_json() { assert_eq!( Compiler::new() - .define_global("invalid_array", json!({ "foo": null })) + .define_global("invalid_struct", json!({ "foo": null })) .unwrap_err(), VariableError::UnexpectedNull ); + + assert_eq!( + Compiler::new() + .define_global("invalid_struct", json!({ "/foo": 1 })) + .unwrap_err(), + VariableError::InvalidIdentifier("/foo".to_string()) + ); } #[test] diff --git a/lib/src/variables.rs b/lib/src/variables.rs index 62c60d084..9b7a7d3c2 100644 --- a/lib/src/variables.rs +++ b/lib/src/variables.rs @@ -37,7 +37,7 @@ pub enum VariableError { /// The identifier is not valid. Identifiers can only contain alphanumeric /// characters and underscores, and can't start with a digit. - #[error("invalid variable identifier `{0}`")] + #[error("invalid identifier `{0}`")] InvalidIdentifier(String), /// The value of a variable cannot be null. This may happen when using a @@ -303,6 +303,11 @@ impl TryFrom<&serde_json::Value> for Variable { serde_json::Value::Object(obj) => { let mut s = types::Struct::new(); for (key, value) in obj { + if !is_valid_identifier(key) { + return Err(VariableError::InvalidIdentifier( + key.to_string(), + )); + } s.add_field( key, TypeValue::from(Variable::try_from(value)?), diff --git a/py/src/lib.rs b/py/src/lib.rs index 03916a3ed..a305bd333 100644 --- a/py/src/lib.rs +++ b/py/src/lib.rs @@ -497,7 +497,10 @@ impl Compiler { /// each scanner can change the variable's value by calling /// [`crate::Scanner::set_global`]. /// - /// The type of `value` must be: bool, str, bytes, int or float. + /// The type of `value` must be: bool, str, bytes, int, float or dict. When + /// the value is a dict, keys must be of type string and valid YARA identifiers + /// (the first character must be `_` or a letter, and the remaining ones must + /// be a `_`, a letter or a digit). /// /// # Raises /// diff --git a/py/yara_x.pyi b/py/yara_x.pyi index 358c7652e..5067688c4 100644 --- a/py/yara_x.pyi +++ b/py/yara_x.pyi @@ -96,7 +96,10 @@ class Compiler: each scanner can change the variable's value by calling [`crate::Scanner::set_global`]. - The type of `value` must be: bool, str, bytes, int or float. + The type of `value` must be: bool, str, bytes, int, float or dict. When + the value is a dict, keys must be of type string and valid YARA identifiers + (the first character must be `_` or a letter, and the remaining ones must + be a `_`, a letter or a digit). # Raises