You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by mg...@apache.org on 2022/06/28 09:45:18 UTC

[avro] branch avro-3549-better-error-handling-for-missing-feature created (now e53ae59de)

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

mgrigorov pushed a change to branch avro-3549-better-error-handling-for-missing-feature
in repository https://gitbox.apache.org/repos/asf/avro.git


      at e53ae59de AVRO-3549: [rust] Avro reader fails if it tries to read data compressed with codec that is not enabled in features

This branch includes the following new commits:

     new e53ae59de AVRO-3549: [rust] Avro reader fails if it tries to read data compressed with codec that is not enabled in features

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[avro] 01/01: AVRO-3549: [rust] Avro reader fails if it tries to read data compressed with codec that is not enabled in features

Posted by mg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch avro-3549-better-error-handling-for-missing-feature
in repository https://gitbox.apache.org/repos/asf/avro.git

commit e53ae59de42d2ba3a4de937ceb1f689f11db6b0f
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
AuthorDate: Tue Jun 28 12:44:13 2022 +0300

    AVRO-3549: [rust] Avro reader fails if it tries to read data compressed with codec that is not enabled in features
    
    Return a proper error when the codec is not supported and/or enabled.
    
    Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
---
 lang/rust/avro/src/error.rs  |  9 ++++++
 lang/rust/avro/src/reader.rs | 67 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs
index 1e1e685ab..ec6e22aee 100644
--- a/lang/rust/avro/src/error.rs
+++ b/lang/rust/avro/src/error.rs
@@ -47,6 +47,9 @@ pub enum Error {
     #[error("Invalid utf-8 string")]
     ConvertToUtf8(#[source] std::string::FromUtf8Error),
 
+    #[error("Invalid utf-8 string")]
+    ConvertToUtf8Error(#[source] std::str::Utf8Error),
+
     /// Describes errors happened while validating Avro data.
     #[error("Value does not match schema")]
     Validation,
@@ -424,6 +427,12 @@ pub enum Error {
         "Internal buffer not drained properly. Re-initialize the single object writer struct!"
     )]
     IllegalSingleObjectWriterState,
+
+    #[error("Codec '{0}' is not supported/enabled")]
+    CodecNotSupported(String),
+
+    #[error("Invalid Avro data! Cannot read codec type from value that is not Value::Bytes.")]
+    BadCodecMetadata,
 }
 
 impl serde::ser::Error for Error {
diff --git a/lang/rust/avro/src/reader.rs b/lang/rust/avro/src/reader.rs
index 72513bf1e..b4db0c355 100644
--- a/lang/rust/avro/src/reader.rs
+++ b/lang/rust/avro/src/reader.rs
@@ -82,7 +82,7 @@ impl<R: Read> Block<R> {
 
         if let Value::Map(metadata) = decode(&meta_schema, &mut self.reader)? {
             self.read_writer_schema(&metadata)?;
-            self.read_codec(&metadata);
+            self.codec = read_codec(&metadata)?;
 
             for (key, value) in metadata {
                 if key == "avro.schema" || key == "avro.codec" {
@@ -199,22 +199,6 @@ impl<R: Read> Block<R> {
         Ok(())
     }
 
-    fn read_codec(&mut self, metadata: &HashMap<String, Value>) {
-        if let Some(codec) = metadata
-            .get("avro.codec")
-            .and_then(|codec| {
-                if let Value::Bytes(ref bytes) = *codec {
-                    std::str::from_utf8(bytes.as_ref()).ok()
-                } else {
-                    None
-                }
-            })
-            .and_then(|codec| Codec::from_str(codec).ok())
-        {
-            self.codec = codec;
-        }
-    }
-
     fn read_user_metadata(&mut self, key: String, value: Value) {
         match value {
             Value::Bytes(ref vec) => {
@@ -230,6 +214,33 @@ impl<R: Read> Block<R> {
     }
 }
 
+fn read_codec(metadata: &HashMap<String, Value>) -> AvroResult<Codec> {
+    let result = metadata
+        .get("avro.codec")
+        .map(|codec| {
+            if let Value::Bytes(ref bytes) = *codec {
+                match std::str::from_utf8(bytes.as_ref()) {
+                    Ok(utf8) => Ok(utf8),
+                    Err(utf8_error) => Err(Error::ConvertToUtf8Error(utf8_error)),
+                }
+            } else {
+                Err(Error::BadCodecMetadata)
+            }
+        })
+        .map(|codec_res| match codec_res {
+            Ok(codec) => match Codec::from_str(codec) {
+                Ok(codec) => Ok(codec),
+                Err(_) => Err(Error::CodecNotSupported(codec.to_owned())),
+            },
+            Err(err) => Err(err),
+        });
+
+    match result {
+        Some(res) => res,
+        None => Ok(Codec::Null),
+    }
+}
+
 /// Main interface for reading Avro formatted values.
 ///
 /// To be used as an iterator:
@@ -821,4 +832,26 @@ mod tests {
         assert_eq!(obj, read_obj2);
         assert_eq!(val, expected_value)
     }
+
+    #[test]
+    fn test_avro_3549_read_not_enabled_codec() {
+        let snappy_compressed_avro = vec![
+            79, 98, 106, 1, 4, 22, 97, 118, 114, 111, 46, 115, 99, 104, 101, 109, 97, 210, 1, 123,
+            34, 102, 105, 101, 108, 100, 115, 34, 58, 91, 123, 34, 110, 97, 109, 101, 34, 58, 34,
+            110, 117, 109, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110,
+            103, 34, 125, 93, 44, 34, 110, 97, 109, 101, 34, 58, 34, 101, 118, 101, 110, 116, 34,
+            44, 34, 110, 97, 109, 101, 115, 112, 97, 99, 101, 34, 58, 34, 101, 120, 97, 109, 112,
+            108, 101, 110, 97, 109, 101, 115, 112, 97, 99, 101, 34, 44, 34, 116, 121, 112, 101, 34,
+            58, 34, 114, 101, 99, 111, 114, 100, 34, 125, 20, 97, 118, 114, 111, 46, 99, 111, 100,
+            101, 99, 12, 115, 110, 97, 112, 112, 121, 0, 213, 209, 241, 208, 200, 110, 164, 47,
+            203, 25, 90, 235, 161, 167, 195, 177, 2, 20, 4, 12, 6, 49, 50, 51, 115, 38, 58, 0, 213,
+            209, 241, 208, 200, 110, 164, 47, 203, 25, 90, 235, 161, 167, 195, 177,
+        ];
+
+        if let Err(err) = Reader::new(snappy_compressed_avro.as_slice()) {
+            assert_eq!("Codec 'snappy' is not supported/enabled", err.to_string());
+        } else {
+            panic!("Expected an error in the reading of the codec!");
+        }
+    }
 }