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(())
+ }
}