Skip to content

Commit

Permalink
Fix deserialization of u64
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Sep 13, 2024
1 parent 538a6f1 commit f177481
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
72 changes: 71 additions & 1 deletion src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,51 @@ impl<'de> Deserializer<'de> {
_ => Err(Error::DeserializeBadU32),
}
}
fn raw_deserialize_u64(&mut self, major: u8) -> Result<u64> {
let additional = self.expect_major(major)?;

match additional {
byte @ 0..=23 => Ok(byte as u64),
24 => match self.try_take_n(1)?[0] {
0..=23 => Err(Error::DeserializeNonMinimal),
byte => Ok(byte as u64),
},
25 => {
let unsigned = u16::from_be_bytes(
self.try_take_n(2)?
.try_into()
.map_err(|_| Error::InexistentSliceToArrayError)?,
);
match unsigned {
0..=255 => Err(Error::DeserializeNonMinimal),
unsigned => Ok(unsigned as u64),
}
}
26 => {
let unsigned = u32::from_be_bytes(
self.try_take_n(4)?
.try_into()
.map_err(|_| Error::InexistentSliceToArrayError)?,
);
match unsigned {
0..=65535 => Err(Error::DeserializeNonMinimal),
unsigned => Ok(unsigned as u64),
}
}
27 => {
let unsigned = u64::from_be_bytes(
self.try_take_n(8)?
.try_into()
.map_err(|_| Error::InexistentSliceToArrayError)?,
);
match unsigned {
0..=0xFFFFFFFF => Err(Error::DeserializeNonMinimal),
unsigned => Ok(unsigned),
}
}
_ => Err(Error::DeserializeBadU64),
}
}

// fn try_take_varint(&mut self) -> Result<usize> {
// for i in 0..VarintUsize::varint_usize_max() {
Expand Down Expand Up @@ -425,7 +470,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
let raw = self.raw_deserialize_u32(MAJOR_POSINT)?;
let raw = self.raw_deserialize_u64(MAJOR_POSINT)?;
visitor.visit_u64(raw as u64)
}

Expand Down Expand Up @@ -831,6 +876,31 @@ mod tests {
}
}

#[test]
fn de_u64() {
let mut buf = [0u8; 64];

let numbers = [
0,
1,
2,
3,
u16::MAX as u64,
u16::MAX as u64 + 1,
u32::MAX as u64,
u32::MAX as u64 + 1,
u64::MAX - 1,
u64::MAX,
];

for number in numbers {
println!("testing {}", number);
let _n = cbor_serialize(&number, &mut buf).unwrap();
let de: u64 = from_bytes(&buf).unwrap();
assert_eq!(de, number);
}
}

#[test]
fn de_i32() {
let mut buf = [0u8; 64];
Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub enum Error {
DeserializeBadU16,
/// Expected a u32
DeserializeBadU32,
/// Expected a u64
DeserializeBadU64,
/// Expected a NULL marker
DeserializeExpectedNull,
/// Inexistent slice-to-array cast error. Used here to avoid calling unwrap.
Expand Down Expand Up @@ -93,6 +95,7 @@ impl Display for Error {
DeserializeBadU8 => "Expected a u8",
DeserializeBadU16 => "Expected a u16",
DeserializeBadU32 => "Expected a u32",
DeserializeBadU64 => "Expected a u64",
DeserializeExpectedNull => "Expected 0xf6",
InexistentSliceToArrayError => "",
DeserializeNonMinimal => "Value may be valid, but not encoded in minimal way",
Expand Down

0 comments on commit f177481

Please sign in to comment.