diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 971702c..9bb739e 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -51,7 +51,11 @@ impl Block { } let height = u64::from_be_bytes(bytes[0..8].try_into().ok()?); let parent: [u8; 32] = bytes[8..40].try_into().ok()?; - let event_count = u64::from_be_bytes(bytes[40..48].try_into().ok()?) as usize; + let event_count = + usize::try_from(u64::from_be_bytes(bytes[40..48].try_into().ok()?)).ok()?; + if event_count > (bytes.len() - 48) / 16 { + return None; + } let mut events = Vec::with_capacity(event_count); let mut offset = 48; @@ -95,12 +99,13 @@ impl Event { return None; } let block_height = u64::from_be_bytes(bytes[0..8].try_into().ok()?); - let len = u64::from_be_bytes(bytes[8..16].try_into().ok()?) as usize; - if bytes.len() < 16 + len { + let len = usize::try_from(u64::from_be_bytes(bytes[8..16].try_into().ok()?)).ok()?; + let end = 16usize.checked_add(len)?; + if bytes.len() < end { return None; } - let data = bytes[16..16 + len].to_vec(); - Some((Self { block_height, data }, 16 + len)) + let data = bytes[16..end].to_vec(); + Some((Self { block_height, data }, end)) } } @@ -133,11 +138,12 @@ impl Proof { return None; } let block_height = u64::from_be_bytes(bytes[0..8].try_into().ok()?); - let len = u64::from_be_bytes(bytes[8..16].try_into().ok()?) as usize; - if bytes.len() < 16 + len { + let len = usize::try_from(u64::from_be_bytes(bytes[8..16].try_into().ok()?)).ok()?; + let end = 16usize.checked_add(len)?; + if bytes.len() < end { return None; } - let data = bytes[16..16 + len].to_vec(); - Some((Self { block_height, data }, 16 + len)) + let data = bytes[16..end].to_vec(); + Some((Self { block_height, data }, end)) } } diff --git a/crates/types/tests/block_serialization.rs b/crates/types/tests/block_serialization.rs index 29fad69..d163957 100644 --- a/crates/types/tests/block_serialization.rs +++ b/crates/types/tests/block_serialization.rs @@ -6,8 +6,14 @@ fn test_block_roundtrip() { height: 42, parent: [0xab; 32], events: vec![ - Event { block_height: 42, data: vec![1, 2, 3] }, - Event { block_height: 42, data: vec![4, 5, 6, 7] }, + Event { + block_height: 42, + data: vec![1, 2, 3], + }, + Event { + block_height: 42, + data: vec![4, 5, 6, 7], + }, ], }; @@ -54,3 +60,22 @@ fn test_event_with_block_height_roundtrip() { assert_eq!(recovered.data, vec![0xde, 0xad, 0xbe, 0xef]); assert_eq!(consumed, bytes.len()); } + +#[test] +fn test_event_rejects_oversized_length_prefix() { + let mut bytes = Vec::new(); + bytes.extend(42u64.to_be_bytes()); + bytes.extend(u64::MAX.to_be_bytes()); + + assert!(Event::from_bytes(&bytes).is_none()); +} + +#[test] +fn test_block_rejects_oversized_event_count() { + let mut bytes = Vec::new(); + bytes.extend(42u64.to_be_bytes()); + bytes.extend([0xab; 32]); + bytes.extend(u64::MAX.to_be_bytes()); + + assert!(Block::from_bytes(&bytes).is_none()); +}