diff --git a/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs b/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs index 6d5985931..6c6f0b9bc 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs @@ -1112,4 +1112,43 @@ mod tests { RPCError::InvalidData ); } + + /// Test sending a message with encoded length prefix > MAX_RPC_SIZE. + #[test] + fn test_decode_invalid_length() { + // 10 byte snappy stream identifier + let stream_identifier: &'static [u8] = b"\xFF\x06\x00\x00sNaPpY"; + + assert_eq!(stream_identifier.len(), 10); + + // Status message is 84 bytes uncompressed. `max_compressed_len` is 32 + 84 + 84/6 = 130. + let status_message_bytes = StatusMessage { + fork_digest: [0; 4], + finalized_root: Hash256::from_low_u64_be(0), + finalized_epoch: Epoch::new(1), + head_root: Hash256::from_low_u64_be(0), + head_slot: Slot::new(1), + } + .as_ssz_bytes(); + + let mut uvi_codec: Uvi = Uvi::default(); + let mut dst = BytesMut::with_capacity(1024); + + // Insert length-prefix + uvi_codec.encode(MAX_RPC_SIZE + 1, &mut dst).unwrap(); + + // Insert snappy stream identifier + dst.extend_from_slice(stream_identifier); + + // Insert payload + let mut writer = FrameEncoder::new(Vec::new()); + writer.write_all(&status_message_bytes).unwrap(); + writer.flush().unwrap(); + dst.extend_from_slice(writer.get_ref()); + + assert_eq!( + decode(Protocol::Status, Version::V1, &mut dst).unwrap_err(), + RPCError::InvalidData + ); + } } diff --git a/beacon_node/lighthouse_network/src/rpc/outbound.rs b/beacon_node/lighthouse_network/src/rpc/outbound.rs index 891125534..1c908887e 100644 --- a/beacon_node/lighthouse_network/src/rpc/outbound.rs +++ b/beacon_node/lighthouse_network/src/rpc/outbound.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use super::methods::*; use super::protocol::Protocol; -use super::protocol::ProtocolId; +use super::protocol::{ProtocolId, MAX_RPC_SIZE}; use super::RPCError; use crate::rpc::protocol::Encoding; use crate::rpc::protocol::Version; @@ -150,7 +150,7 @@ where Encoding::SSZSnappy => { let ssz_snappy_codec = BaseOutboundCodec::new(SSZSnappyOutboundCodec::new( protocol, - usize::max_value(), + MAX_RPC_SIZE, self.fork_context.clone(), )); OutboundCodec::SSZSnappy(ssz_snappy_codec) diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index b85e48d31..c00b9c049 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -81,7 +81,7 @@ lazy_static! { } /// The maximum bytes that can be sent across the RPC. -const MAX_RPC_SIZE: usize = 1_048_576; // 1M +pub const MAX_RPC_SIZE: usize = 1_048_576; // 1M /// The protocol prefix the RPC protocol id. const PROTOCOL_PREFIX: &str = "/eth2/beacon_chain/req"; /// Time allowed for the first byte of a request to arrive before we time out (Time To First Byte).