parent
230df0ec0c
commit
a0514eb2ae
|
@ -161,7 +161,7 @@ pub struct PruneData {
|
||||||
impl Sanitize for PruneData {
|
impl Sanitize for PruneData {
|
||||||
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
||||||
if self.wallclock >= MAX_WALLCLOCK {
|
if self.wallclock >= MAX_WALLCLOCK {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -2822,7 +2822,7 @@ mod tests {
|
||||||
let mut pd = PruneData::default();
|
let mut pd = PruneData::default();
|
||||||
pd.wallclock = MAX_WALLCLOCK;
|
pd.wallclock = MAX_WALLCLOCK;
|
||||||
let msg = Protocol::PruneMessage(Pubkey::default(), pd);
|
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
|
// computes the maximum size for pull request blooms
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub struct ContactInfo {
|
||||||
impl Sanitize for ContactInfo {
|
impl Sanitize for ContactInfo {
|
||||||
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
||||||
if self.wallclock >= MAX_WALLCLOCK {
|
if self.wallclock >= MAX_WALLCLOCK {
|
||||||
return Err(SanitizeError::Failed);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -325,4 +325,12 @@ mod tests {
|
||||||
ci.rpc = socketaddr!("127.0.0.1:234");
|
ci.rpc = socketaddr!("127.0.0.1:234");
|
||||||
assert!(ci.valid_client_facing_addr().is_some());
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,13 +83,13 @@ impl Sanitize for CrdsData {
|
||||||
CrdsData::ContactInfo(val) => val.sanitize(),
|
CrdsData::ContactInfo(val) => val.sanitize(),
|
||||||
CrdsData::Vote(ix, val) => {
|
CrdsData::Vote(ix, val) => {
|
||||||
if *ix >= MAX_VOTES {
|
if *ix >= MAX_VOTES {
|
||||||
return Err(SanitizeError::Failed);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
val.sanitize()
|
val.sanitize()
|
||||||
}
|
}
|
||||||
CrdsData::LowestSlot(ix, val) => {
|
CrdsData::LowestSlot(ix, val) => {
|
||||||
if *ix as usize >= 1 {
|
if *ix as usize >= 1 {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
val.sanitize()
|
val.sanitize()
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ impl Sanitize for CrdsData {
|
||||||
CrdsData::AccountsHashes(val) => val.sanitize(),
|
CrdsData::AccountsHashes(val) => val.sanitize(),
|
||||||
CrdsData::EpochSlots(ix, val) => {
|
CrdsData::EpochSlots(ix, val) => {
|
||||||
if *ix as usize >= MAX_EPOCH_SLOTS as usize {
|
if *ix as usize >= MAX_EPOCH_SLOTS as usize {
|
||||||
return Err(SanitizeError::Failed);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
val.sanitize()
|
val.sanitize()
|
||||||
}
|
}
|
||||||
|
@ -115,11 +115,11 @@ pub struct SnapshotHash {
|
||||||
impl Sanitize for SnapshotHash {
|
impl Sanitize for SnapshotHash {
|
||||||
fn sanitize(&self) -> Result<(), SanitizeError> {
|
fn sanitize(&self) -> Result<(), SanitizeError> {
|
||||||
if self.wallclock >= MAX_WALLCLOCK {
|
if self.wallclock >= MAX_WALLCLOCK {
|
||||||
return Err(SanitizeError::Failed);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
for (slot, _) in &self.hashes {
|
for (slot, _) in &self.hashes {
|
||||||
if *slot >= MAX_SLOT {
|
if *slot >= MAX_SLOT {
|
||||||
return Err(SanitizeError::Failed);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.from.sanitize()
|
self.from.sanitize()
|
||||||
|
@ -161,10 +161,10 @@ impl LowestSlot {
|
||||||
impl Sanitize for LowestSlot {
|
impl Sanitize for LowestSlot {
|
||||||
fn sanitize(&self) -> Result<(), SanitizeError> {
|
fn sanitize(&self) -> Result<(), SanitizeError> {
|
||||||
if self.wallclock >= MAX_WALLCLOCK {
|
if self.wallclock >= MAX_WALLCLOCK {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
if self.lowest >= MAX_SLOT {
|
if self.lowest >= MAX_SLOT {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
if self.root != 0 {
|
if self.root != 0 {
|
||||||
return Err(SanitizeError::InvalidValue);
|
return Err(SanitizeError::InvalidValue);
|
||||||
|
@ -189,7 +189,7 @@ pub struct Vote {
|
||||||
impl Sanitize for Vote {
|
impl Sanitize for Vote {
|
||||||
fn sanitize(&self) -> Result<(), SanitizeError> {
|
fn sanitize(&self) -> Result<(), SanitizeError> {
|
||||||
if self.wallclock >= MAX_WALLCLOCK {
|
if self.wallclock >= MAX_WALLCLOCK {
|
||||||
return Err(SanitizeError::Failed);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
self.from.sanitize()?;
|
self.from.sanitize()?;
|
||||||
self.transaction.sanitize()
|
self.transaction.sanitize()
|
||||||
|
@ -448,7 +448,7 @@ mod test {
|
||||||
|
|
||||||
let o = ls.clone();
|
let o = ls.clone();
|
||||||
let v = CrdsValue::new_unsigned(CrdsData::LowestSlot(1, o.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();
|
let mut o = ls.clone();
|
||||||
o.slots.insert(1);
|
o.slots.insert(1);
|
||||||
|
@ -505,7 +505,7 @@ mod test {
|
||||||
),
|
),
|
||||||
&keypair,
|
&keypair,
|
||||||
);
|
);
|
||||||
assert!(item.sanitize().is_err());
|
assert_eq!(item.sanitize(), Err(SanitizeError::ValueOutOfBounds));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_compute_vote_index_empty() {
|
fn test_compute_vote_index_empty() {
|
||||||
|
|
|
@ -19,10 +19,10 @@ pub struct Uncompressed {
|
||||||
impl Sanitize for Uncompressed {
|
impl Sanitize for Uncompressed {
|
||||||
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
||||||
if self.first_slot >= MAX_SLOT {
|
if self.first_slot >= MAX_SLOT {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
if self.num >= MAX_SLOTS_PER_ENTRY {
|
if self.num >= MAX_SLOTS_PER_ENTRY {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,10 @@ pub struct Flate2 {
|
||||||
impl Sanitize for Flate2 {
|
impl Sanitize for Flate2 {
|
||||||
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
||||||
if self.first_slot >= MAX_SLOT {
|
if self.first_slot >= MAX_SLOT {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
if self.num >= MAX_SLOTS_PER_ENTRY {
|
if self.num >= MAX_SLOTS_PER_ENTRY {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ pub struct EpochSlots {
|
||||||
impl Sanitize for EpochSlots {
|
impl Sanitize for EpochSlots {
|
||||||
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
|
||||||
if self.wallclock >= MAX_WALLCLOCK {
|
if self.wallclock >= MAX_WALLCLOCK {
|
||||||
return Err(SanitizeError::ValueOutOfRange);
|
return Err(SanitizeError::ValueOutOfBounds);
|
||||||
}
|
}
|
||||||
self.from.sanitize()?;
|
self.from.sanitize()?;
|
||||||
self.slots.sanitize()
|
self.slots.sanitize()
|
||||||
|
@ -387,22 +387,22 @@ mod tests {
|
||||||
|
|
||||||
let mut o = slots.clone();
|
let mut o = slots.clone();
|
||||||
o.first_slot = MAX_SLOT;
|
o.first_slot = MAX_SLOT;
|
||||||
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
|
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));
|
||||||
|
|
||||||
let mut o = slots.clone();
|
let mut o = slots.clone();
|
||||||
o.num = MAX_SLOTS_PER_ENTRY;
|
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();
|
let compressed = Flate2::deflate(slots).unwrap();
|
||||||
assert!(compressed.sanitize().is_ok());
|
assert!(compressed.sanitize().is_ok());
|
||||||
|
|
||||||
let mut o = compressed.clone();
|
let mut o = compressed.clone();
|
||||||
o.first_slot = MAX_SLOT;
|
o.first_slot = MAX_SLOT;
|
||||||
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
|
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));
|
||||||
|
|
||||||
let mut o = compressed.clone();
|
let mut o = compressed.clone();
|
||||||
o.num = MAX_SLOTS_PER_ENTRY;
|
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 mut slots = EpochSlots::default();
|
||||||
let range: Vec<Slot> = (0..5000).into_iter().collect();
|
let range: Vec<Slot> = (0..5000).into_iter().collect();
|
||||||
|
@ -412,7 +412,7 @@ mod tests {
|
||||||
|
|
||||||
let mut o = slots.clone();
|
let mut o = slots.clone();
|
||||||
o.wallclock = MAX_WALLCLOCK;
|
o.wallclock = MAX_WALLCLOCK;
|
||||||
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfRange));
|
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! The `hash` module provides functions for creating SHA-256 hashes.
|
//! The `hash` module provides functions for creating SHA-256 hashes.
|
||||||
|
|
||||||
|
use crate::sanitize::Sanitize;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::{convert::TryFrom, fmt, mem, str::FromStr};
|
use std::{convert::TryFrom, fmt, mem, str::FromStr};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -30,6 +31,8 @@ impl Hasher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sanitize for Hash {}
|
||||||
|
|
||||||
impl AsRef<[u8]> for Hash {
|
impl AsRef<[u8]> for Hash {
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
&self.0[..]
|
&self.0[..]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Defines a composable Instruction type and a memory-efficient CompiledInstruction.
|
//! Defines a composable Instruction type and a memory-efficient CompiledInstruction.
|
||||||
|
|
||||||
|
use crate::sanitize::Sanitize;
|
||||||
use crate::{pubkey::Pubkey, short_vec, system_instruction::SystemError};
|
use crate::{pubkey::Pubkey, short_vec, system_instruction::SystemError};
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
@ -252,6 +253,8 @@ pub struct CompiledInstruction {
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sanitize for CompiledInstruction {}
|
||||||
|
|
||||||
impl CompiledInstruction {
|
impl CompiledInstruction {
|
||||||
pub fn new<T: Serialize>(program_ids_index: u8, data: &T, accounts: Vec<u8>) -> Self {
|
pub fn new<T: Serialize>(program_ids_index: u8, data: &T, accounts: Vec<u8>) -> Self {
|
||||||
let data = serialize(data).unwrap();
|
let data = serialize(data).unwrap();
|
||||||
|
|
|
@ -184,6 +184,9 @@ impl Sanitize for Message {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.account_keys.sanitize()?;
|
||||||
|
self.recent_blockhash.sanitize()?;
|
||||||
|
self.instructions.sanitize()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
#[derive(PartialEq, Debug)]
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Error, Eq, Clone)]
|
||||||
pub enum SanitizeError {
|
pub enum SanitizeError {
|
||||||
Failed,
|
#[error("index out of bounds")]
|
||||||
IndexOutOfBounds,
|
IndexOutOfBounds,
|
||||||
ValueOutOfRange,
|
#[error("value out of bounds")]
|
||||||
|
ValueOutOfBounds,
|
||||||
|
#[error("invalid value")]
|
||||||
InvalidValue,
|
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 {
|
pub trait Sanitize {
|
||||||
fn sanitize(&self) -> Result<(), SanitizeError> {
|
fn sanitize(&self) -> Result<(), SanitizeError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue