solana_bincode/
lib.rs

1//! Contains a single utility function for deserializing from [bincode].
2//!
3//! [bincode]: https://docs.rs/bincode
4
5use {bincode::config::Options, solana_instruction::error::InstructionError};
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::*, solana_program::system_instruction::SystemInstruction};
24
25    #[test]
26    fn test_limited_deserialize_advance_nonce_account() {
27        let item = SystemInstruction::AdvanceNonceAccount;
28        let mut 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        serialized.push(0);
43        assert_eq!(
44            limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
45            Ok(&item)
46        );
47    }
48}