Skip to content

Commit

Permalink
proptest: fuzz and fix a number of deserialization impls
Browse files Browse the repository at this point in the history
  • Loading branch information
bmwill committed Feb 27, 2024
1 parent 5d66a2b commit c4ecf7f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 7 deletions.
55 changes: 53 additions & 2 deletions src/types/crypto/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,12 @@ mod serialization {
{
let b64: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
let bytes = Base64::decode_vec(&b64).map_err(serde::de::Error::custom)?;
let flag = SignatureScheme::from_byte(bytes[0]).map_err(serde::de::Error::custom)?;
let flag = SignatureScheme::from_byte(
*bytes
.first()
.ok_or_else(|| serde::de::Error::custom("missing signature scheme falg"))?,
)
.map_err(serde::de::Error::custom)?;
let public_key_bytes = &bytes[1..];
match flag {
SignatureScheme::Ed25519 => {
Expand Down Expand Up @@ -461,7 +466,12 @@ mod serialization {
bytes: T,
) -> Result<Self, E> {
let bytes = bytes.as_ref();
let flag = SignatureScheme::from_byte(bytes[0]).map_err(serde::de::Error::custom)?;
let flag = SignatureScheme::from_byte(
*bytes
.first()
.ok_or_else(|| serde::de::Error::custom("missing signature scheme falg"))?,
)
.map_err(serde::de::Error::custom)?;
if flag != SignatureScheme::Multisig {
return Err(serde::de::Error::custom("invalid multisig flag"));
}
Expand Down Expand Up @@ -734,4 +744,45 @@ mod serialization {
}
}
}

#[cfg(test)]
mod test {
use super::*;
use test_strategy::proptest;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[proptest]
fn fuzz_deserialization_multisig_member_public_key(
#[strategy(proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=2048))]
bytes: Vec<u8>,
) {
let _: Result<MultisigMemberPublicKey, _> = bcs::from_bytes(&bytes);
}

#[proptest]
fn fuzz_deserialization_multisig_member(
#[strategy(proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=2048))]
bytes: Vec<u8>,
) {
let _: Result<MultisigMember, _> = bcs::from_bytes(&bytes);
}

#[proptest]
fn fuzz_deserialization_multisig_committee(
#[strategy(proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=2048))]
bytes: Vec<u8>,
) {
let _: Result<MultisigCommittee, _> = bcs::from_bytes(&bytes);
}

#[proptest]
fn fuzz_deserialization_multisig_member_signature(
#[strategy(proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=2048))]
bytes: Vec<u8>,
) {
let _: Result<MultisigMemberSignature, _> = bcs::from_bytes(&bytes);
}
}
}
30 changes: 26 additions & 4 deletions src/types/crypto/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ impl SimpleSignature {
#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
fn from_serialized_bytes<T: AsRef<[u8]>, E: serde::de::Error>(bytes: T) -> Result<Self, E> {
let bytes = bytes.as_ref();
let flag = SignatureScheme::from_byte(bytes[0]).map_err(serde::de::Error::custom)?;
let flag = SignatureScheme::from_byte(
*bytes
.first()
.ok_or_else(|| serde::de::Error::custom("missing signature scheme falg"))?,
)
.map_err(serde::de::Error::custom)?;
match flag {
SignatureScheme::Ed25519 => {
let expected_length = 1 + Ed25519Signature::LENGTH + Ed25519PublicKey::LENGTH;
Expand Down Expand Up @@ -438,7 +443,10 @@ mod serialization {
let bytes: std::borrow::Cow<'de, [u8]> =
serde_with::Bytes::deserialize_as(deserializer)?;
let flag =
SignatureScheme::from_byte(bytes[0]).map_err(serde::de::Error::custom)?;
SignatureScheme::from_byte(*bytes.first().ok_or_else(|| {
serde::de::Error::custom("missing signature scheme falg")
})?)
.map_err(serde::de::Error::custom)?;
match flag {
SignatureScheme::Ed25519
| SignatureScheme::Secp256k1
Expand Down Expand Up @@ -473,21 +481,35 @@ mod serialization {
use wasm_bindgen_test::wasm_bindgen_test as test;

#[proptest]
#[cfg(feature = "serde")]
fn roundtrip_bcs(signature: UserSignature) {
let b = bcs::to_bytes(&signature).unwrap();
let s = bcs::from_bytes(&b).unwrap();
assert_eq!(signature, s);
}

#[proptest]
#[cfg(feature = "serde")]
fn roundtrip_json(signature: UserSignature) {
let s = serde_json::to_string(&signature).unwrap();
let sig = serde_json::from_str(&s).unwrap();
assert_eq!(signature, sig);
}

#[proptest]
fn fuzz_deserialization_user_signature(
#[strategy(proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=2048))]
bytes: Vec<u8>,
) {
let _: Result<UserSignature, _> = bcs::from_bytes(&bytes);
}

#[proptest]
fn fuzz_deserialization_simple_signature(
#[strategy(proptest::collection::vec(proptest::arbitrary::any::<u8>(), 0..=2048))]
bytes: Vec<u8>,
) {
let _: Result<SimpleSignature, _> = bcs::from_bytes(&bytes);
}

#[test]
fn simple_fixtures() {
const FIXTURES: &[(SignatureScheme, &str)] = &[
Expand Down
4 changes: 3 additions & 1 deletion src/types/crypto/zklogin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ mod serialization {
Ok(Self { iss, address_seed })
} else {
let bytes: Cow<'de, [u8]> = Bytes::deserialize_as(deserializer)?;
let iss_len = bytes[0];
let iss_len = *bytes
.first()
.ok_or_else(|| serde::de::Error::custom("invalid zklogin public identifier"))?;
let iss_bytes = bytes
.get(1..(1 + iss_len as usize))
.ok_or_else(|| serde::de::Error::custom("invalid zklogin public identifier"))?;
Expand Down

0 comments on commit c4ecf7f

Please sign in to comment.