This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch branch-1.11
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/branch-1.11 by this push:
     new 9de1895ff AVRO-3827: [Rust] Disallow duplicate field names (#2433)
9de1895ff is described below

commit 9de1895ffb74f927213ec604f5f62bbed81d4754
Author: Kousuke Saruta <[email protected]>
AuthorDate: Thu Aug 10 16:28:57 2023 +0900

    AVRO-3827: [Rust] Disallow duplicate field names (#2433)
    
    * AVRO-3827: [Rust] Disallow duplicate field names
    
    * Reuse BTreeMap.
    
    * Use the returned Option.
    
    (cherry picked from commit 3deb73c840fe2b966cda0094f8114f47cf6b131e)
---
 lang/rust/avro/src/error.rs  |  3 ++
 lang/rust/avro/src/schema.rs | 71 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs
index 661223313..c0c279bfa 100644
--- a/lang/rust/avro/src/error.rs
+++ b/lang/rust/avro/src/error.rs
@@ -307,6 +307,9 @@ pub enum Error {
     #[error("Invalid field name {0}")]
     FieldName(String),
 
+    #[error("Duplicate field name {0}")]
+    FieldNameDuplicate(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 45333cf37..7f9a8198d 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -1441,7 +1441,9 @@ impl Parser {
             })?;
 
         for field in &fields {
-            lookup.insert(field.name.clone(), field.position);
+            if let Some(_old) = lookup.insert(field.name.clone(), 
field.position) {
+                return Err(Error::FieldNameDuplicate(field.name.clone()));
+            }
 
             if let Some(ref field_aliases) = field.aliases {
                 for alias in field_aliases {
@@ -5026,4 +5028,71 @@ mod tests {
             other => Err(format!("Expected Error::FieldName, got 
{other:?}").into()),
         }
     }
+
+    #[test]
+    fn test_avro_3827_disallow_duplicate_field_names() -> TestResult {
+        let schema_str = r#"
+        {
+          "name": "my_schema",
+          "type": "record",
+          "fields": [
+            {
+              "name": "f1",
+              "type": {
+                "name": "a",
+                "type": "record",
+                "fields": []
+              }
+            },  {
+              "name": "f1",
+              "type": {
+                "name": "b",
+                "type": "record",
+                "fields": []
+              }
+            }
+          ]
+        }
+        "#;
+
+        match Schema::parse_str(schema_str) {
+            Err(Error::FieldNameDuplicate(_)) => (),
+            other => {
+                return Err(format!("Expected Error::FieldNameDuplicate, got 
{other:?}").into())
+            }
+        };
+
+        let schema_str = r#"
+        {
+          "name": "my_schema",
+          "type": "record",
+          "fields": [
+            {
+              "name": "f1",
+              "type": {
+                "name": "a",
+                "type": "record",
+                "fields": [
+                  {
+                    "name": "f1",
+                    "type": {
+                      "name": "b",
+                      "type": "record",
+                      "fields": []
+                    }
+                  }
+                ]
+              }
+            }
+          ]
+        }
+        "#;
+
+        let expected = 
r#"{"name":"my_schema","type":"record","fields":[{"name":"f1","type":{"name":"a","type":"record","fields":[{"name":"f1","type":{"name":"b","type":"record","fields":[]}}]}}]}"#;
+        let schema = Schema::parse_str(schema_str)?;
+        let canonical_form = schema.canonical_form();
+        assert_eq!(canonical_form, expected);
+
+        Ok(())
+    }
 }

Reply via email to