From 6bfb4921929e7f238df3ac165d598f73c5a82757 Mon Sep 17 00:00:00 2001
From: librelois <c@elo.tf>
Date: Sun, 13 Jun 2021 17:32:37 +0200
Subject: [PATCH] fix(kv_typed): zerocopy slice deser not handle correctly
 empty slice

---
 tools/kv_typed/src/collection_ro.rs       |  2 +-
 tools/kv_typed/src/from_bytes.rs          | 28 +++++++++++++++--------
 tools/kv_typed/src/iter.rs                | 10 +++++---
 tools/kv_typed/src/transactional_read.rs  |  2 +-
 tools/kv_typed/src/transactional_write.rs |  2 +-
 5 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/tools/kv_typed/src/collection_ro.rs b/tools/kv_typed/src/collection_ro.rs
index 3a1aa0c..78e6f47 100644
--- a/tools/kv_typed/src/collection_ro.rs
+++ b/tools/kv_typed/src/collection_ro.rs
@@ -193,7 +193,7 @@ impl<V: ValueSliceZc, BC: BackendCol, E: EventTrait<V = V>> DbCollectionRoGetRef
     ) -> KvResult<Option<D>> {
         let r = self.inner.read();
         r.backend_col.get_ref_slice::<E::K, V, D, _>(k, |bytes| {
-            if bytes.is_empty() {
+            if bytes.len() <= V::prefix_len() {
                 f(&[])
             } else if let Some(layout_verified) =
                 zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice(&bytes[V::prefix_len()..])
diff --git a/tools/kv_typed/src/from_bytes.rs b/tools/kv_typed/src/from_bytes.rs
index 6cade2d..1646e7b 100644
--- a/tools/kv_typed/src/from_bytes.rs
+++ b/tools/kv_typed/src/from_bytes.rs
@@ -63,9 +63,13 @@ where
     type Err = LayoutVerifiedErr;
 
     fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> {
-        let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes)
-            .ok_or(LayoutVerifiedErr(stringify!(T)))?;
-        Ok(SmallVec::from_slice(layout_verified.into_slice()))
+        if bytes.is_empty() {
+            Ok(SmallVec::new())
+        } else {
+            let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes)
+                .ok_or(LayoutVerifiedErr(stringify!(T)))?;
+            Ok(SmallVec::from_slice(layout_verified.into_slice()))
+        }
     }
 }
 
@@ -76,13 +80,17 @@ where
     type Err = LayoutVerifiedErr;
 
     fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> {
-        let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes)
-            .ok_or(LayoutVerifiedErr(stringify!(Vec<T>)))?;
-        let slice = layout_verified.into_slice();
-        let mut vec = Vec::with_capacity(slice.len());
-        vec.resize_with(slice.len(), Default::default);
-        vec.copy_from_slice(slice);
-        Ok(vec)
+        if bytes.is_empty() {
+            Ok(Vec::with_capacity(0))
+        } else {
+            let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes)
+                .ok_or(LayoutVerifiedErr(stringify!(Vec<T>)))?;
+            let slice = layout_verified.into_slice();
+            let mut vec = Vec::with_capacity(slice.len());
+            vec.resize_with(slice.len(), Default::default);
+            vec.copy_from_slice(slice);
+            Ok(vec)
+        }
     }
 }
 
diff --git a/tools/kv_typed/src/iter.rs b/tools/kv_typed/src/iter.rs
index 8671cb1..2625db8 100644
--- a/tools/kv_typed/src/iter.rs
+++ b/tools/kv_typed/src/iter.rs
@@ -175,9 +175,13 @@ where
             Some(Ok((k_bytes, v_bytes))) => {
                 if let Some(k_layout) = zerocopy::LayoutVerified::<_, K::Ref>::new(k_bytes.as_ref())
                 {
-                    if let Some(v_layout) = zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice(
-                        &v_bytes.as_ref()[V::prefix_len()..],
-                    ) {
+                    if v_bytes.as_ref().len() <= V::prefix_len() {
+                        Some((self.f)(&k_layout, &[]))
+                    } else if let Some(v_layout) =
+                        zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice(
+                            &v_bytes.as_ref()[V::prefix_len()..],
+                        )
+                    {
                         Some((self.f)(&k_layout, &v_layout))
                     } else {
                         Some(Err(KvError::DeserError(
diff --git a/tools/kv_typed/src/transactional_read.rs b/tools/kv_typed/src/transactional_read.rs
index 75df9be..5828a72 100644
--- a/tools/kv_typed/src/transactional_read.rs
+++ b/tools/kv_typed/src/transactional_read.rs
@@ -138,7 +138,7 @@ impl<'tx, V: ValueSliceZc, BC: BackendCol, E: EventTrait<V = V>> TxColRo<'tx, BC
         self.col_reader
             .backend_col
             .get_ref_slice::<E::K, V, D, _>(k, |bytes| {
-                if bytes.is_empty() {
+                if bytes.len() <= V::prefix_len() {
                     f(&[])
                 } else if let Some(layout_verified) =
                     zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice(&bytes[V::prefix_len()..])
diff --git a/tools/kv_typed/src/transactional_write.rs b/tools/kv_typed/src/transactional_write.rs
index 54d109d..5e500c1 100644
--- a/tools/kv_typed/src/transactional_write.rs
+++ b/tools/kv_typed/src/transactional_write.rs
@@ -62,7 +62,7 @@ impl<'tx, V: ValueSliceZc, BC: BackendCol, E: EventTrait<V = V>> TxColRw<'tx, BC
         self.col_reader
             .backend_col
             .get_ref_slice::<E::K, V, D, _>(k, |bytes| {
-                if bytes.is_empty() {
+                if bytes.len() <= V::prefix_len() {
                     f(&[])
                 } else if let Some(layout_verified) =
                     zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice(&bytes[V::prefix_len()..])
-- 
GitLab