Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nits for sanitize trait #9741

Merged
merged 1 commit into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/src/cluster_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ pub struct PruneData {
impl Sanitize for PruneData {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
if self.wallclock >= MAX_WALLCLOCK {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
Ok(())
}
Expand Down Expand Up @@ -2822,7 +2822,7 @@ mod tests {
let mut pd = PruneData::default();
pd.wallclock = MAX_WALLCLOCK;
let msg = Protocol::PruneMessage(Pubkey::default(), pd);
assert_eq!(msg.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(msg.sanitize(), Err(SanitizeError::ValueOutOfBounds));
}

// computes the maximum size for pull request blooms
Expand Down
10 changes: 9 additions & 1 deletion core/src/contact_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct ContactInfo {
impl Sanitize for ContactInfo {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
if self.wallclock >= MAX_WALLCLOCK {
return Err(SanitizeError::Failed);
return Err(SanitizeError::ValueOutOfBounds);
}
Ok(())
}
Expand Down Expand Up @@ -325,4 +325,12 @@ mod tests {
ci.rpc = socketaddr!("127.0.0.1:234");
assert!(ci.valid_client_facing_addr().is_some());
}

#[test]
fn test_sanitize() {
let mut ci = ContactInfo::default();
assert_eq!(ci.sanitize(), Ok(()));
ci.wallclock = MAX_WALLCLOCK;
assert_eq!(ci.sanitize(), Err(SanitizeError::ValueOutOfBounds));
}
}
20 changes: 10 additions & 10 deletions core/src/crds_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,21 @@ impl Sanitize for CrdsData {
CrdsData::ContactInfo(val) => val.sanitize(),
CrdsData::Vote(ix, val) => {
if *ix >= MAX_VOTES {
return Err(SanitizeError::Failed);
return Err(SanitizeError::ValueOutOfBounds);
}
val.sanitize()
}
CrdsData::LowestSlot(ix, val) => {
if *ix as usize >= 1 {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
val.sanitize()
}
CrdsData::SnapshotHashes(val) => val.sanitize(),
CrdsData::AccountsHashes(val) => val.sanitize(),
CrdsData::EpochSlots(ix, val) => {
if *ix as usize >= MAX_EPOCH_SLOTS as usize {
return Err(SanitizeError::Failed);
return Err(SanitizeError::ValueOutOfBounds);
}
val.sanitize()
}
Expand All @@ -115,11 +115,11 @@ pub struct SnapshotHash {
impl Sanitize for SnapshotHash {
fn sanitize(&self) -> Result<(), SanitizeError> {
if self.wallclock >= MAX_WALLCLOCK {
return Err(SanitizeError::Failed);
return Err(SanitizeError::ValueOutOfBounds);
}
for (slot, _) in &self.hashes {
if *slot >= MAX_SLOT {
return Err(SanitizeError::Failed);
return Err(SanitizeError::ValueOutOfBounds);
}
}
self.from.sanitize()
Expand Down Expand Up @@ -161,10 +161,10 @@ impl LowestSlot {
impl Sanitize for LowestSlot {
fn sanitize(&self) -> Result<(), SanitizeError> {
if self.wallclock >= MAX_WALLCLOCK {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
if self.lowest >= MAX_SLOT {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
if self.root != 0 {
return Err(SanitizeError::InvalidValue);
Expand All @@ -189,7 +189,7 @@ pub struct Vote {
impl Sanitize for Vote {
fn sanitize(&self) -> Result<(), SanitizeError> {
if self.wallclock >= MAX_WALLCLOCK {
return Err(SanitizeError::Failed);
return Err(SanitizeError::ValueOutOfBounds);
}
self.from.sanitize()?;
self.transaction.sanitize()
Expand Down Expand Up @@ -448,7 +448,7 @@ mod test {

let o = ls.clone();
let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(1, o.clone()));
assert_eq!(v.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(v.sanitize(), Err(SanitizeError::ValueOutOfBounds));

let mut o = ls.clone();
o.slots.insert(1);
Expand Down Expand Up @@ -505,7 +505,7 @@ mod test {
),
&keypair,
);
assert!(item.sanitize().is_err());
assert_eq!(item.sanitize(), Err(SanitizeError::ValueOutOfBounds));
}
#[test]
fn test_compute_vote_index_empty() {
Expand Down
20 changes: 10 additions & 10 deletions core/src/epoch_slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ pub struct Uncompressed {
impl Sanitize for Uncompressed {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
if self.first_slot >= MAX_SLOT {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
if self.num >= MAX_SLOTS_PER_ENTRY {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
Ok(())
}
Expand All @@ -38,10 +38,10 @@ pub struct Flate2 {
impl Sanitize for Flate2 {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
if self.first_slot >= MAX_SLOT {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
if self.num >= MAX_SLOTS_PER_ENTRY {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
Ok(())
}
Expand Down Expand Up @@ -221,7 +221,7 @@ pub struct EpochSlots {
impl Sanitize for EpochSlots {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
if self.wallclock >= MAX_WALLCLOCK {
return Err(SanitizeError::ValueOutOfRange);
return Err(SanitizeError::ValueOutOfBounds);
}
self.from.sanitize()?;
self.slots.sanitize()
Expand Down Expand Up @@ -387,22 +387,22 @@ mod tests {

let mut o = slots.clone();
o.first_slot = MAX_SLOT;
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));

let mut o = slots.clone();
o.num = MAX_SLOTS_PER_ENTRY;
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));

let compressed = Flate2::deflate(slots).unwrap();
assert!(compressed.sanitize().is_ok());

let mut o = compressed.clone();
o.first_slot = MAX_SLOT;
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));

let mut o = compressed.clone();
o.num = MAX_SLOTS_PER_ENTRY;
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));

let mut slots = EpochSlots::default();
let range: Vec<Slot> = (0..5000).into_iter().collect();
Expand All @@ -412,7 +412,7 @@ mod tests {

let mut o = slots.clone();
o.wallclock = MAX_WALLCLOCK;
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));
}

#[test]
Expand Down
3 changes: 3 additions & 0 deletions sdk/src/hash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! The `hash` module provides functions for creating SHA-256 hashes.
use crate::sanitize::Sanitize;
use sha2::{Digest, Sha256};
use std::{convert::TryFrom, fmt, mem, str::FromStr};
use thiserror::Error;
Expand Down Expand Up @@ -30,6 +31,8 @@ impl Hasher {
}
}

impl Sanitize for Hash {}

impl AsRef<[u8]> for Hash {
fn as_ref(&self) -> &[u8] {
&self.0[..]
Expand Down
3 changes: 3 additions & 0 deletions sdk/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Defines a composable Instruction type and a memory-efficient CompiledInstruction.

use crate::sanitize::Sanitize;
use crate::{pubkey::Pubkey, short_vec, system_instruction::SystemError};
use bincode::serialize;
use serde::Serialize;
Expand Down Expand Up @@ -252,6 +253,8 @@ pub struct CompiledInstruction {
pub data: Vec<u8>,
}

impl Sanitize for CompiledInstruction {}

impl CompiledInstruction {
pub fn new<T: Serialize>(program_ids_index: u8, data: &T, accounts: Vec<u8>) -> Self {
let data = serialize(data).unwrap();
Expand Down
3 changes: 3 additions & 0 deletions sdk/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ impl Sanitize for Message {
}
}
}
self.account_keys.sanitize()?;
self.recent_blockhash.sanitize()?;
self.instructions.sanitize()?;
Ok(())
}
}
Expand Down
17 changes: 14 additions & 3 deletions sdk/src/sanitize.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
#[derive(PartialEq, Debug)]
use thiserror::Error;

#[derive(PartialEq, Debug, Error, Eq, Clone)]
pub enum SanitizeError {
Failed,
#[error("index out of bounds")]
IndexOutOfBounds,
ValueOutOfRange,
#[error("value out of bounds")]
ValueOutOfBounds,
#[error("invalid value")]
InvalidValue,
}

/// Trait for sanitizing values and members of over the wire messages.
/// Implementation should recursively decent through the data structure
/// and sanitize all struct members and enum clauses. Sanitize excludes
/// signature verification checks, those are handled by another pass.
/// Sanitize checks should include but are not limited too:
/// * All index values are in range
/// * All values are within their static max/min bounds
pub trait Sanitize {
fn sanitize(&self) -> Result<(), SanitizeError> {
Ok(())
Expand Down