diff --git a/rlp/src/rlpin.rs b/rlp/src/rlpin.rs index fed936c..58b2ce7 100644 --- a/rlp/src/rlpin.rs +++ b/rlp/src/rlpin.rs @@ -40,6 +40,7 @@ pub enum Prototype { } /// Stores basic information about item +#[derive(Debug)] pub struct PayloadInfo { /// Header length in bytes pub header_len: usize, @@ -258,8 +259,10 @@ impl<'a> Rlp<'a> { /// consumes first found prefix fn consume_list_payload(&self) -> Result<&'a [u8], DecoderError> { let item = BasicDecoder::payload_info(self.bytes)?; - let bytes = Rlp::consume(self.bytes, item.header_len)?; - Ok(bytes) + if self.bytes.len() < (item.header_len + item.value_len) { + return Err(DecoderError::RlpIsTooShort); + } + Ok(&self.bytes[item.header_len..item.header_len + item.value_len]) } /// consumes fixed number of items diff --git a/rlp/tests/tests.rs b/rlp/tests/tests.rs index 84af86b..2dc1e94 100644 --- a/rlp/tests/tests.rs +++ b/rlp/tests/tests.rs @@ -437,4 +437,28 @@ fn test_rlp_is_int() { let rlp = Rlp::new(&data); assert_eq!(rlp.is_int(), false); } -} \ No newline at end of file +} + +/// test described in +/// +/// https://github.com/paritytech/parity-common/issues/48 +#[test] +fn test_inner_length_capping_for_short_lists() { + assert_eq!(Rlp::new(&vec![0xc0 + 0, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); + assert_eq!(Rlp::new(&vec![0xc0 + 1, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); + assert_eq!(Rlp::new(&vec![0xc0 + 2, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); + assert_eq!(Rlp::new(&vec![0xc0 + 3, 0x82, b'a', b'b']).val_at::(0), Ok("ab".to_owned())); + assert_eq!(Rlp::new(&vec![0xc0 + 4, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); +} + +/// test described in +/// +/// https://github.com/paritytech/parity-common/issues/48 +#[test] +fn test_inner_length_capping_for_long_lists() { + assert_eq!(Rlp::new(&vec![0xf7 + 1, 0, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpDataLenWithZeroPrefix)); + assert_eq!(Rlp::new(&vec![0xf7 + 1, 1, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); + assert_eq!(Rlp::new(&vec![0xf7 + 1, 2, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); + assert_eq!(Rlp::new(&vec![0xf7 + 1, 3, 0x82, b'a', b'b']).val_at::(0), Ok("ab".to_owned())); + assert_eq!(Rlp::new(&vec![0xf7 + 1, 4, 0x82, b'a', b'b']).val_at::(0), Err(DecoderError::RlpIsTooShort)); +}