cbe_program/
program_utils.rs

1//! Contains a single utility function for deserializing from [bincode].
2//!
3//! [bincode]: https://docs.cartallum.com/bincode
4
5use {crate::instruction::InstructionError, bincode::config::Options};
6
7/// Deserialize with a limit based the maximum amount of data a program can expect to get.
8/// This function should be used in place of direct deserialization to help prevent OOM errors
9pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
10where
11    T: serde::de::DeserializeOwned,
12{
13    bincode::options()
14        .with_limit(limit)
15        .with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
16        .allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
17        .deserialize_from(instruction_data)
18        .map_err(|_| InstructionError::InvalidInstructionData)
19}
20
21#[cfg(test)]
22pub mod tests {
23    use {super::*, cbe_program::system_instruction::SystemInstruction};
24
25    #[test]
26    fn test_limited_deserialize_advance_nonce_account() {
27        let item = SystemInstruction::AdvanceNonceAccount;
28        let serialized = bincode::serialize(&item).unwrap();
29
30        assert_eq!(
31            serialized.len(),
32            4,
33            "`SanitizedMessage::get_durable_nonce()` may need a change"
34        );
35
36        assert_eq!(
37            limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
38            Ok(&item)
39        );
40        assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());
41    }
42}