| 
									
										
										
										
											2020-06-17 10:39:14 -07:00
										 |  |  | use crate::instruction::InstructionError;
 | 
					
						
							| 
									
										
										
										
											2020-07-09 00:08:05 +00:00
										 |  |  | use 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-09 00:08:05 +00: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 15:54:42 -06:00
										 |  |  |         .deserialize_from(instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-10-23 19:56:07 -07:00
										 |  |  |         .map_err(|_| InstructionError::InvalidInstructionData)
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-07-08 15:54:42 -06: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());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 |