From db359f50d44c2440fde15215f8dd46ec0eacc559 Mon Sep 17 00:00:00 2001 From: Kousuke Saruta Date: Fri, 4 Aug 2023 16:33:21 +0900 Subject: [PATCH] Fix to deny invalid field names. (#2414) --- lang/rust/avro/src/error.rs | 3 +++ lang/rust/avro/src/schema.rs | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs index 908dab7704d..97c929ad780 100644 --- a/lang/rust/avro/src/error.rs +++ b/lang/rust/avro/src/error.rs @@ -307,6 +307,9 @@ pub enum Error { #[error("Invalid enum symbol name {0}")] EnumSymbolName(String), + #[error("Invalid field name {0}")] + FieldName(String), + #[error("Invalid schema name {0}. It must match the regex '{1}'")] InvalidSchemaName(String, &'static str), diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs index 9ab6ce7ec41..6185bb67201 100644 --- a/lang/rust/avro/src/schema.rs +++ b/lang/rust/avro/src/schema.rs @@ -43,6 +43,8 @@ lazy_static! { // An optional namespace (with optional dots) followed by a name without any dots in it. static ref SCHEMA_NAME_R: Regex = Regex::new(r"^((?P[A-Za-z_][A-Za-z0-9_\.]*)*\.)?(?P[A-Za-z_][A-Za-z0-9_]*)$").unwrap(); + + static ref FIELD_NAME_R: Regex = Regex::new(r"^[A-Za-z_][A-Za-z0-9_]*$").unwrap(); } /// Represents an Avro schema fingerprint @@ -622,6 +624,10 @@ impl RecordField { ) -> AvroResult { let name = field.name().ok_or(Error::GetNameFieldFromRecord)?; + if !FIELD_NAME_R.is_match(&name) { + return Err(Error::FieldName(name)); + } + // TODO: "type" = "" let schema = parser.parse_complex(field, enclosing_namespace)?; @@ -5026,4 +5032,36 @@ mod tests { Ok(()) } + + #[test] + fn test_avro_3820_deny_invalid_field_names() -> TestResult { + let schema_str = r#" + { + "name": "my_record", + "type": "record", + "fields": [ + { + "name": "f1.x", + "type": { + "name": "my_enum", + "type": "enum", + "symbols": ["a"] + } + }, { + "name": "f2", + "type": { + "name": "my_fixed", + "type": "fixed", + "size": 1 + } + } + ] + } + "#; + + match Schema::parse_str(schema_str) { + Err(Error::FieldName(x)) if x == "f1.x" => Ok(()), + other => Err(format!("Expected Error::FieldName, got {other:?}").into()), + } + } }