2021-12-03 09:00:31 -08:00
|
|
|
use {crate::instruction::InstructionError, bincode::config::Options};
|
2020-01-10 13:20:15 -08:00
|
|
|
|
2020-02-04 17:04:26 -08:00
|
|
|
/// Deserialize with a limit based the maximum amount of data a program can expect to get.
|
|
|
|
/// This function should be used in place of direct deserialization to help prevent OOM errors
|
2020-01-20 15:27:36 -08:00
|
|
|
pub fn limited_deserialize<T>(instruction_data: &[u8]) -> Result<T, InstructionError>
|
2019-10-23 19:56:07 -07:00
|
|
|
where
|
|
|
|
T: serde::de::DeserializeOwned,
|
|
|
|
{
|
|
|
|
let limit = crate::packet::PACKET_DATA_SIZE as u64;
|
2020-07-08 17:08:05 -07:00
|
|
|
bincode::options()
|
|
|
|
.with_limit(limit)
|
|
|
|
.with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
|
|
|
|
.allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
|
2020-07-08 14:54:42 -07:00
|
|
|
.deserialize_from(instruction_data)
|
2019-10-23 19:56:07 -07:00
|
|
|
.map_err(|_| InstructionError::InvalidInstructionData)
|
|
|
|
}
|
2020-07-08 14:54:42 -07:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_limited_deserialize() {
|
|
|
|
#[derive(Deserialize, Serialize)]
|
|
|
|
enum Foo {
|
|
|
|
Bar(Vec<u8>),
|
|
|
|
}
|
|
|
|
|
|
|
|
let item = Foo::Bar([1; crate::packet::PACKET_DATA_SIZE - 12].to_vec()); // crate::packet::PACKET_DATA_SIZE - 12: size limit, minus enum variant and vec len() serialized sizes
|
|
|
|
let serialized = bincode::serialize(&item).unwrap();
|
|
|
|
assert!(limited_deserialize::<Foo>(&serialized).is_ok());
|
|
|
|
|
|
|
|
let item = Foo::Bar([1; crate::packet::PACKET_DATA_SIZE - 11].to_vec()); // Extra byte should bump serialized size over the size limit
|
|
|
|
let serialized = bincode::serialize(&item).unwrap();
|
|
|
|
assert!(limited_deserialize::<Foo>(&serialized).is_err());
|
|
|
|
}
|
|
|
|
}
|