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

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


The following commit(s) were added to refs/heads/master by this push:
     new adc0b5a2e [Rust]: Incorrect decimal resolving checks (#2289)
adc0b5a2e is described below

commit adc0b5a2edd422eacc0665f2786b7ac615bbe16c
Author: theo <[email protected]>
AuthorDate: Thu Jun 15 09:54:20 2023 +0300

    [Rust]: Incorrect decimal resolving checks (#2289)
    
    * feat: add failing test case
    
    * AVRO-3782: [Rust] Incorrect decimal resolving
    
    Fix the check for max precision that a byte array could provide
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    
    ---------
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    Co-authored-by: Fedor Telnov <[email protected]>
    Co-authored-by: Martin Tzvetanov Grigorov <[email protected]>
---
 lang/rust/avro/src/types.rs | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/lang/rust/avro/src/types.rs b/lang/rust/avro/src/types.rs
index 6ecadda0a..b0a022347 100644
--- a/lang/rust/avro/src/types.rs
+++ b/lang/rust/avro/src/types.rs
@@ -694,7 +694,7 @@ impl Value {
         match self {
             Value::Decimal(num) => {
                 let num_bytes = num.len();
-                if max_prec_for_len(num_bytes)? > precision {
+                if max_prec_for_len(num_bytes)? < precision {
                     Err(Error::ComparePrecisionAndSize {
                         precision,
                         num_bytes,
@@ -705,7 +705,7 @@ impl Value {
                 // check num.bits() here
             }
             Value::Fixed(_, bytes) | Value::Bytes(bytes) => {
-                if max_prec_for_len(bytes.len())? > precision {
+                if max_prec_for_len(bytes.len())? < precision {
                     Err(Error::ComparePrecisionAndSize {
                         precision,
                         num_bytes: bytes.len(),
@@ -1035,6 +1035,7 @@ mod tests {
         logger::{assert_logged, assert_not_logged},
         TestResult,
     };
+    use num_bigint::BigInt;
     use pretty_assertions::assert_eq;
     use uuid::Uuid;
 
@@ -1500,7 +1501,7 @@ Field with name '"b"' is not a member of the map items"#,
 
     #[test]
     fn resolve_decimal_bytes() -> TestResult {
-        let value = Value::Decimal(Decimal::from(vec![1, 2]));
+        let value = Value::Decimal(Decimal::from(vec![1, 2, 3, 4, 5]));
         value.clone().resolve(&Schema::Decimal(DecimalSchema {
             precision: 10,
             scale: 4,
@@ -1513,7 +1514,7 @@ Field with name '"b"' is not a member of the map items"#,
 
     #[test]
     fn resolve_decimal_invalid_scale() {
-        let value = Value::Decimal(Decimal::from(vec![1]));
+        let value = Value::Decimal(Decimal::from(vec![1, 2]));
         assert!(value
             .resolve(&Schema::Decimal(DecimalSchema {
                 precision: 2,
@@ -1532,12 +1533,12 @@ Field with name '"b"' is not a member of the map 
items"#,
                 scale: 0,
                 inner: Box::new(Schema::Bytes),
             }))
-            .is_err());
+            .is_ok());
     }
 
     #[test]
     fn resolve_decimal_fixed() {
-        let value = Value::Decimal(Decimal::from(vec![1, 2]));
+        let value = Value::Decimal(Decimal::from(vec![1, 2, 3, 4, 5]));
         assert!(value
             .clone()
             .resolve(&Schema::Decimal(DecimalSchema {
@@ -2763,4 +2764,21 @@ Field with name '"b"' is not a member of the map items"#,
 
         Ok(())
     }
+
+    #[test]
+    fn test_avro_3782_incorrect_decimal_resolving() -> TestResult {
+        let schema = r#"{"name": "decimalSchema", "logicalType": "decimal", 
"type": "fixed", "precision": 8, "scale": 0, "size": 8}"#;
+
+        let avro_value = Value::Decimal(Decimal::from(
+            BigInt::from(12345678u32).to_signed_bytes_be(),
+        ));
+        let schema = Schema::parse_str(schema)?;
+        let resolve_result = avro_value.resolve(&schema);
+        assert!(
+            resolve_result.is_ok(),
+            "resolve result must be ok, got: {resolve_result:?}"
+        );
+
+        Ok(())
+    }
 }

Reply via email to