node: Test that message encoding doesn't panic

Previously, it was possible for the `wire::serialize` function to panic
due to large ref announcements. Now that ref announcements are properly
bounded in size, this shouldn't happen anymore.
This commit is contained in:
cloudhead 2023-11-16 13:20:00 +01:00
parent e71f07e592
commit bea86871de
No known key found for this signature in database
2 changed files with 62 additions and 4 deletions

View File

@ -82,12 +82,17 @@ pub trait Decode: Sized {
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error>;
}
/// Encode an object into a vector.
/// Encode an object into a byte vector.
///
/// # Panics
///
/// If the encoded object exceeds [`Size::MAX`].
pub fn serialize<T: Encode + ?Sized>(data: &T) -> Vec<u8> {
let mut buffer = Vec::new();
let len = data
.encode(&mut buffer)
.expect("in-memory writes don't error");
// SAFETY: We expect this to panic if the user passes
// in data that exceeds the maximum allowed size.
#[allow(clippy::unwrap_used)]
let len = data.encode(&mut buffer).unwrap();
debug_assert_eq!(len, buffer.len());

View File

@ -371,10 +371,63 @@ impl wire::Decode for ZeroBytes {
mod tests {
use super::*;
use qcheck_macros::quickcheck;
use radicle::storage::refs::RefsAt;
use radicle_crypto::test::signer::MockSigner;
use crate::deserializer::Deserializer;
use crate::test::arbitrary;
use crate::wire::{self, Encode};
#[test]
fn test_refs_ann_max_size() {
let signer = MockSigner::default();
let refs: [RefsAt; REF_REMOTE_LIMIT] = arbitrary::gen(1);
let ann = AnnouncementMessage::Refs(RefsAnnouncement {
rid: arbitrary::gen(1),
refs: BoundedVec::collect_from(&mut refs.into_iter()),
timestamp: arbitrary::gen(1),
});
let ann = ann.signed(&signer);
let msg = Message::Announcement(ann);
let data = wire::serialize(&msg);
assert!(data.len() < wire::Size::MAX as usize);
}
#[test]
fn test_inv_ann_max_size() {
let signer = MockSigner::default();
let inv: [Id; INVENTORY_LIMIT] = arbitrary::gen(1);
let ann = AnnouncementMessage::Inventory(InventoryAnnouncement {
inventory: BoundedVec::collect_from(&mut inv.into_iter()),
timestamp: arbitrary::gen(1),
});
let ann = ann.signed(&signer);
let msg = Message::Announcement(ann);
let data = wire::serialize(&msg);
assert!(data.len() < wire::Size::MAX as usize);
}
#[test]
fn test_node_ann_max_size() {
let signer = MockSigner::default();
let addrs: [Address; ADDRESS_LIMIT] = arbitrary::gen(1);
let alias = ['@'; radicle::node::MAX_ALIAS_LENGTH];
let ann = AnnouncementMessage::Node(NodeAnnouncement {
features: Default::default(),
alias: radicle::node::Alias::new(String::from_iter(alias)),
addresses: BoundedVec::collect_from(&mut addrs.into_iter()),
timestamp: arbitrary::gen(1),
nonce: u64::MAX,
});
let ann = ann.signed(&signer);
let msg = Message::Announcement(ann);
let data = wire::serialize(&msg);
assert!(data.len() < wire::Size::MAX as usize);
}
#[test]
fn test_pingpong_encode_max_size() {
let mut buf = Vec::new();