From 1f7b7ec49807cc5e38b032bc1995ce05c29dc283 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sat, 11 May 2019 19:09:27 +1000 Subject: [PATCH] Add tests for SSZ offset attacks --- eth2/utils/ssz/src/decode.rs | 5 ++++ eth2/utils/ssz/tests/tests.rs | 51 ++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/eth2/utils/ssz/src/decode.rs b/eth2/utils/ssz/src/decode.rs index 194a3360a0..ea7238365f 100644 --- a/eth2/utils/ssz/src/decode.rs +++ b/eth2/utils/ssz/src/decode.rs @@ -100,9 +100,14 @@ impl<'a> SszDecoderBuilder<'a> { fn apply_offsets(&mut self) -> Result<(), DecodeError> { if !self.offsets.is_empty() { + let mut insertions = 0; let mut running_offset = self.offsets[0].offset; + if running_offset != self.items_index { + return Err(DecodeError::OutOfBoundsByte { i: running_offset }) + } + for i in 1..=self.offsets.len() { let (slice_option, position) = if i == self.offsets.len() { (self.bytes.get(running_offset..), self.offsets.len()) diff --git a/eth2/utils/ssz/tests/tests.rs b/eth2/utils/ssz/tests/tests.rs index 5b0a013693..44d8435466 100644 --- a/eth2/utils/ssz/tests/tests.rs +++ b/eth2/utils/ssz/tests/tests.rs @@ -1,5 +1,5 @@ use ethereum_types::H256; -use ssz::{Decodable, Encodable}; +use ssz::{Decodable, DecodeError, Encodable}; use ssz_derive::{Decode, Encode}; mod round_trip { @@ -125,6 +125,34 @@ mod round_trip { c: u32, } + #[test] + fn offset_into_fixed_bytes() { + let bytes = vec![ + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // | offset | u32 | variable + 01, 00, 09, 00, 00, 00, 01, 00, 00, 00, 00, 00, 01, 00, 02, 00, + ]; + + assert_eq!( + VariableLen::from_ssz_bytes(&bytes), + Err(DecodeError::OutOfBoundsByte { i: 9 }) + ); + } + + #[test] + fn first_offset_skips_byte() { + let bytes = vec![ + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // | offset | u32 | variable + 01, 00, 11, 00, 00, 00, 01, 00, 00, 00, 00, 00, 01, 00, 02, 00, + ]; + + assert_eq!( + VariableLen::from_ssz_bytes(&bytes), + Err(DecodeError::OutOfBoundsByte { i: 11 }) + ); + } + #[test] fn variable_len_struct_encoding() { let items: Vec = vec![ @@ -193,4 +221,25 @@ mod round_trip { round_trip(items); } + #[derive(Debug, PartialEq, Encode, Decode)] + struct ThreeVariableLen { + a: u16, + b: Vec, + c: Vec, + d: Vec, + } + + #[test] + fn offsets_decreasing() { + let bytes = vec![ + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // | offset | ofset | offset | variable + 01, 00, 14, 00, 00, 00, 15, 00, 00, 00, 14, 00, 00, 00, 00, 00, + ]; + + assert_eq!( + ThreeVariableLen::from_ssz_bytes(&bytes), + Err(DecodeError::OutOfBoundsByte { i: 14 }) + ); + } }