adds sanity checks to Shred::reference_tick_from_data

Shred::reference_tick_from_data should check if payload is indeed a data
shred and has valid size.
This commit is contained in:
behzad nouri 2022-05-18 09:23:04 -04:00
parent e2bbc3913d
commit be1d606dea
3 changed files with 16 additions and 12 deletions

View File

@ -1850,10 +1850,8 @@ impl Blockstore {
let upper_index = cmp::min(current_index, end_index); let upper_index = cmp::min(current_index, end_index);
// the tick that will be used to figure out the timeout for this hole // the tick that will be used to figure out the timeout for this hole
let reference_tick = u64::from(Shred::reference_tick_from_data( let data = db_iterator.value().expect("couldn't read value");
db_iterator.value().expect("couldn't read value"), let reference_tick = u64::from(Shred::reference_tick_from_data(data).unwrap());
));
if ticks_since_first_insert < reference_tick + MAX_TURBINE_DELAY_IN_TICKS { if ticks_since_first_insert < reference_tick + MAX_TURBINE_DELAY_IN_TICKS {
// The higher index holes have not timed out yet // The higher index holes have not timed out yet
break 'outer; break 'outer;

View File

@ -483,10 +483,16 @@ impl Shred {
limited_deserialize(buffer).ok() limited_deserialize(buffer).ok()
} }
pub(crate) fn reference_tick_from_data(data: &[u8]) -> u8 { pub(crate) fn reference_tick_from_data(data: &[u8]) -> Result<u8, Error> {
// TODO: should check the type bit as well!
const SHRED_FLAGS_OFFSET: usize = SIZE_OF_COMMON_SHRED_HEADER + std::mem::size_of::<u16>(); const SHRED_FLAGS_OFFSET: usize = SIZE_OF_COMMON_SHRED_HEADER + std::mem::size_of::<u16>();
data[SHRED_FLAGS_OFFSET] & ShredFlags::SHRED_TICK_REFERENCE_MASK.bits() if Self::shred_type_from_payload(data)? != ShredType::Data {
return Err(Error::InvalidShredType);
}
let flags = match data.get(SHRED_FLAGS_OFFSET) {
None => return Err(Error::InvalidPayloadSize(data.len())),
Some(flags) => flags,
};
Ok(flags & ShredFlags::SHRED_TICK_REFERENCE_MASK.bits())
} }
pub fn verify(&self, pubkey: &Pubkey) -> bool { pub fn verify(&self, pubkey: &Pubkey) -> bool {
@ -891,7 +897,7 @@ mod tests {
assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap()); assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap());
assert_eq!( assert_eq!(
shred.reference_tick(), shred.reference_tick(),
Shred::reference_tick_from_data(&packet.data) Shred::reference_tick_from_data(&packet.data).unwrap()
); );
assert_eq!(Shred::get_slot_from_packet(&packet), Some(shred.slot())); assert_eq!(Shred::get_slot_from_packet(&packet), Some(shred.slot()));
assert_eq!( assert_eq!(
@ -932,7 +938,7 @@ mod tests {
assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap()); assert_eq!(shred, Shred::new_from_serialized_shred(payload).unwrap());
assert_eq!( assert_eq!(
shred.reference_tick(), shred.reference_tick(),
Shred::reference_tick_from_data(&packet.data) Shred::reference_tick_from_data(&packet.data).unwrap()
); );
assert_eq!(Shred::get_slot_from_packet(&packet), Some(shred.slot())); assert_eq!(Shred::get_slot_from_packet(&packet), Some(shred.slot()));
assert_eq!( assert_eq!(
@ -1017,7 +1023,7 @@ mod tests {
assert_eq!(shred.last_in_slot(), is_last_in_slot); assert_eq!(shred.last_in_slot(), is_last_in_slot);
assert_eq!(shred.reference_tick(), reference_tick.min(63u8)); assert_eq!(shred.reference_tick(), reference_tick.min(63u8));
assert_eq!( assert_eq!(
Shred::reference_tick_from_data(shred.payload()), Shred::reference_tick_from_data(shred.payload()).unwrap(),
reference_tick.min(63u8), reference_tick.min(63u8),
); );
} }

View File

@ -519,7 +519,7 @@ mod tests {
); );
data_shreds.iter().for_each(|s| { data_shreds.iter().for_each(|s| {
assert_eq!(s.reference_tick(), 5); assert_eq!(s.reference_tick(), 5);
assert_eq!(Shred::reference_tick_from_data(s.payload()), 5); assert_eq!(Shred::reference_tick_from_data(s.payload()).unwrap(), 5);
}); });
let deserialized_shred = let deserialized_shred =
@ -555,7 +555,7 @@ mod tests {
ShredFlags::SHRED_TICK_REFERENCE_MASK.bits() ShredFlags::SHRED_TICK_REFERENCE_MASK.bits()
); );
assert_eq!( assert_eq!(
Shred::reference_tick_from_data(s.payload()), Shred::reference_tick_from_data(s.payload()).unwrap(),
ShredFlags::SHRED_TICK_REFERENCE_MASK.bits() ShredFlags::SHRED_TICK_REFERENCE_MASK.bits()
); );
}); });