From 193dbb179443890718089e64c3f8feddab94a5a7 Mon Sep 17 00:00:00 2001 From: anatoly yakovenko Date: Mon, 27 Apr 2020 20:22:30 -0700 Subject: [PATCH] sanitize lowest slots (#9747) --- core/src/crds_value.rs | 46 +++++++++++++++++++++++++++++++++++++++--- sdk/src/sanitize.rs | 1 + 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/core/src/crds_value.rs b/core/src/crds_value.rs index 82ad19010..baabbe633 100644 --- a/core/src/crds_value.rs +++ b/core/src/crds_value.rs @@ -87,7 +87,12 @@ impl Sanitize for CrdsData { } val.sanitize() } - CrdsData::LowestSlot(_, val) => val.sanitize(), + CrdsData::LowestSlot(ix, val) => { + if *ix as usize >= 1 { + return Err(SanitizeError::ValueOutOfRange); + } + val.sanitize() + } CrdsData::SnapshotHashes(val) => val.sanitize(), CrdsData::AccountsHashes(val) => val.sanitize(), CrdsData::EpochSlots(ix, val) => { @@ -156,10 +161,19 @@ impl LowestSlot { impl Sanitize for LowestSlot { fn sanitize(&self) -> Result<(), SanitizeError> { if self.wallclock >= MAX_WALLCLOCK { - return Err(SanitizeError::Failed); + return Err(SanitizeError::ValueOutOfRange); } if self.lowest >= MAX_SLOT { - return Err(SanitizeError::Failed); + return Err(SanitizeError::ValueOutOfRange); + } + if self.root != 0 { + return Err(SanitizeError::InvalidValue); + } + if !self.slots.is_empty() { + return Err(SanitizeError::InvalidValue); + } + if !self.stash.is_empty() { + return Err(SanitizeError::InvalidValue); } self.from.sanitize() } @@ -421,6 +435,32 @@ mod test { assert_eq!(v.label(), CrdsValueLabel::LowestSlot(key)); } + #[test] + fn test_lowest_slot_sanitize() { + let ls = LowestSlot::new(Pubkey::default(), 0, 0); + let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(0, ls.clone())); + assert_eq!(v.sanitize(), Ok(())); + + let mut o = ls.clone(); + o.root = 1; + let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(0, o.clone())); + assert_eq!(v.sanitize(), Err(SanitizeError::InvalidValue)); + + let o = ls.clone(); + let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(1, o.clone())); + assert_eq!(v.sanitize(), Err(SanitizeError::ValueOutOfRange)); + + let mut o = ls.clone(); + o.slots.insert(1); + let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(0, o.clone())); + assert_eq!(v.sanitize(), Err(SanitizeError::InvalidValue)); + + let mut o = ls.clone(); + o.stash.push(deprecated::EpochIncompleteSlots::default()); + let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(0, o.clone())); + assert_eq!(v.sanitize(), Err(SanitizeError::InvalidValue)); + } + #[test] fn test_signature() { let keypair = Keypair::new(); diff --git a/sdk/src/sanitize.rs b/sdk/src/sanitize.rs index 89681d05b..6ccc638a5 100644 --- a/sdk/src/sanitize.rs +++ b/sdk/src/sanitize.rs @@ -3,6 +3,7 @@ pub enum SanitizeError { Failed, IndexOutOfBounds, ValueOutOfRange, + InvalidValue, } pub trait Sanitize {