diff --git a/Cargo.toml b/Cargo.toml
index 0ec4c5db34e7cd1d07d13261e8ec0121590a1704..30822b32fa82784ab48ea73b882fb53cc68fc4f2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,6 @@ bitvec = { version = "1.0.1", default-features = false }
 crc = "3.0.1"
 encoding_rs = { version = "0.8.33", default-features = false }
 half = { version = "2.3.1", default-features = false }
-labrador-ldpc = "1.1"
+labrador-ldpc = { git = "https://github.com/adamgreig/labrador-ldpc" }
 paste = "1.0.14"
 snafu = { version = "0.7.5", default-features = false }
diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock
index 3093e731f415e7a084a0ce5eb23731c29c721e11..0e8f99a185eb82f3cfc26007c1431793d6f99a7d 100644
--- a/fuzz/Cargo.lock
+++ b/fuzz/Cargo.lock
@@ -96,7 +96,7 @@ dependencies = [
 
 [[package]]
 name = "ham-cats"
-version = "0.1.0"
+version = "0.2.0"
 dependencies = [
  "arrayvec",
  "bitvec",
@@ -133,9 +133,7 @@ dependencies = [
 
 [[package]]
 name = "labrador-ldpc"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ff4a0568f6322b64e06b6a6a0810e2f64670aa325f6e9dca24084e99917f459"
+version = "1.1.1"
 
 [[package]]
 name = "libc"
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index bdfaa004d1686120c248706fdf3d1d8b18e47ce2..7884a306c6025b562ff610f87642233c2d793f5a 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -30,9 +30,14 @@ path = "fuzz_targets/fuzz_target_2.rs"
 test = false
 doc = false
 
-
 [[bin]]
 name = "fuzz_target_3"
 path = "fuzz_targets/fuzz_target_3.rs"
 test = false
 doc = false
+
+[[bin]]
+name = "fuzz_target_4"
+path = "fuzz_targets/fuzz_target_4.rs"
+test = false
+doc = false
diff --git a/fuzz/fuzz_targets/fuzz_target_4.rs b/fuzz/fuzz_targets/fuzz_target_4.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c1482c68944adef29e0b4882e97b93afe4a5ff61
--- /dev/null
+++ b/fuzz/fuzz_targets/fuzz_target_4.rs
@@ -0,0 +1,16 @@
+#![no_main]
+use libfuzzer_sys::fuzz_target;
+
+use ham_cats::packet::Packet;
+use std::convert::TryInto;
+
+fuzz_target!(|data: &[u8]| {
+    // [u8] -> [i8]
+    let mut data: Vec<_> = data
+        .iter()
+        .map(|x| (u16::from(*x) as i16 - 128).try_into().unwrap())
+        .collect();
+
+    let mut buf = [0; 1024];
+    let _ = Packet::<1024>::fully_decode_soft::<8192, i8>(&mut data, &mut buf);
+});
diff --git a/src/interleaver.rs b/src/interleaver.rs
index e6386968ca7868cc31b24fe4b018dd427b1db715..e909ad41a6c1e0135252950bce9beb8cd51ffdd7 100644
--- a/src/interleaver.rs
+++ b/src/interleaver.rs
@@ -87,9 +87,8 @@ pub(crate) fn uninterleave_soft<const N: usize, T: DecodeFrom>(
 
 #[cfg(test)]
 mod tests {
-    use crate::soft_bit::SoftBit;
-
     use super::*;
+    use crate::soft_bit::FromHardBit;
 
     #[test]
     fn interleaver_works() {
diff --git a/src/ldpc.rs b/src/ldpc.rs
index b51a87795a848e2ed497bb21580394f7e604c1b9..65989365e439b104558e026f86dccfb293eb06b9 100644
--- a/src/ldpc.rs
+++ b/src/ldpc.rs
@@ -1,6 +1,6 @@
 use labrador_ldpc::{decoder::DecodeFrom, LDPCCode};
 
-use crate::{buffer::Buffer, error::EncodeError, soft_bit::SoftBit};
+use crate::{buffer::Buffer, error::EncodeError};
 
 macro_rules! enc_chunk {
     ($d:ident, $i:ident, $t:ident, $n:literal) => {
@@ -188,12 +188,14 @@ pub(crate) fn decode_soft<const N: usize, const M: usize, T: DecodeFrom>(
 
     let len: usize = len_from_soft(data_av[(data_av.len() - 16)..].try_into().unwrap()).into();
 
-    if len * 8 >= data_av.len() {
+    if len * 8 + 16 >= data_av.len() {
         return None;
     }
 
-    let (mut data, parity) = data_av.split_at_mut(len * 8);
-    let mut parity = parity.get_mut(..parity.len().checked_sub(16)?)?;
+    let data_len = data_av.len().checked_sub(16)?;
+    let data_av = data_av.get_mut(..data_len)?;
+
+    let (mut data, mut parity) = data_av.split_at_mut(len * 8);
 
     let mut working = [T::zero(); LDPCCode::TM8192.decode_ms_working_len()];
     let mut working_u8 = [0; LDPCCode::TM8192.decode_ms_working_u8_len()];
@@ -276,9 +278,9 @@ fn len_from_soft<T: DecodeFrom>(bits: &[T; 16]) -> u16 {
 
 #[cfg(test)]
 mod tests {
-    use bitvec::{order::Msb0, view::BitView};
-
     use super::*;
+    use crate::soft_bit::FromHardBit;
+    use bitvec::{order::Msb0, view::BitView};
 
     #[test]
     fn len_test() {
diff --git a/src/packet.rs b/src/packet.rs
index 13f9db32c460e1c3f5074d6bd59364f40db0ff34..27b1278d1140f3c1be98c7781052fd91ab164964 100644
--- a/src/packet.rs
+++ b/src/packet.rs
@@ -407,13 +407,12 @@ fn try_lock<'a, const N: usize, T, E, F: Fn(&mut Buffer<'a, N>) -> Result<T, E>>
 
 #[cfg(test)]
 mod tests {
+    use super::*;
+    use crate::soft_bit::FromHardBit;
+    use crate::whisker::NodeInfoBuilder;
     use arrayvec::ArrayString;
     use bitvec::{order::Msb0, view::BitView};
 
-    use crate::{soft_bit::SoftBit, whisker::NodeInfoBuilder};
-
-    use super::*;
-
     #[test]
     fn dest() {
         let d1 = Destination::new(false, 7, "CALL1", 23).unwrap();
@@ -789,4 +788,31 @@ mod tests {
             let _ = Packet::<1024>::decode(buf);
         }
     }
+
+    #[test]
+    fn fully_decode_soft_fuzz_tests() {
+        // When adding to this, don't forget to do the u8 -> i8 conversion
+        let cases = [
+            &mut [
+                -39, -39, -39, -118, -58, -58, -58, -58, -89, -39, -118, -58, -58, -58, 34, 34, 34,
+                34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, -58, -58,
+                127, 81, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+                127, 127, 127, 127, 127, 127, 127, 127, 127, 127, -86, 127, 127, 127, 127, 127,
+                127, 127, 127, 127, 127, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, -58, -58, 127,
+                81, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 34, 34, 34, 34, 34, 34, 34,
+                34, 34, 34, 34, -58, -58, 127, 81, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+                127, 127, 127, 127, 127, 127, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+                -128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, -128, -128,
+            ][..],
+            &mut [
+                -73, -73, -73, -73, -75, -76, -73, -73, -73, -73, -73, -73, -73, -73, 73, 72, 72,
+                72, 72, 72, 72, 62, -73, -118, 120, 127, 127, 121, 127, 112, 127, 127,
+            ],
+        ];
+
+        for data in cases {
+            let mut buf = [0; 1024];
+            let _ = Packet::<1024>::fully_decode_soft::<8192, i8>(data, &mut buf);
+        }
+    }
 }
diff --git a/src/soft_bit.rs b/src/soft_bit.rs
index d2165885e70439f4e3e3e6738d219fce1a57884e..11e9bb2a0d4475c48ff90bed1de99f538c3aaa2f 100644
--- a/src/soft_bit.rs
+++ b/src/soft_bit.rs
@@ -2,12 +2,11 @@ pub use labrador_ldpc::decoder::DecodeFrom;
 
 // Less than zero = 1 bit
 // Greater than zero = 0 bit
-pub trait SoftBit {
+pub trait FromHardBit {
     fn from_hard_bit(bit: bool) -> Self;
-    fn hard_bit(&self) -> bool;
 }
 
-impl<T: DecodeFrom> SoftBit for T {
+impl<T: DecodeFrom> FromHardBit for T {
     fn from_hard_bit(bit: bool) -> Self {
         if bit {
             -Self::one()
@@ -15,10 +14,6 @@ impl<T: DecodeFrom> SoftBit for T {
             Self::one()
         }
     }
-
-    fn hard_bit(&self) -> bool {
-        self < &T::zero()
-    }
 }
 
 #[cfg(test)]