@@ -12,11 +12,21 @@ use {
1212 std:: collections:: BTreeSet ,
1313} ;
1414
15+ // Maximum input buffer length that can be deserialized.
16+ // See `solana_sdk::packet::PACKET_DATA_SIZE`.
17+ const MAX_INPUT_LEN : usize = 1232 ;
18+ // Maximum vector length for a `ConfigKeys` struct's `keys` list.
19+ // See comments below for `safe_deserialize_config_keys`.
20+ //
21+ // Take the maximum input length and subtract (up to) 3 bytes for the
22+ // `ShortU16`, then divide that by the size of a `(Pubkey, bool)` entry.
23+ const MAX_VECTOR_LEN : usize = ( MAX_INPUT_LEN - 3 ) / ( 32 + 1 ) ;
24+
1525// [Core BPF]: The original Config builtin leverages the
1626// `solana_sdk::program_utils::limited_deserialize` method to cap the length of
17- // the input buffer at 1232 (`solana_sdk::packet::PACKET_DATA_SIZE` ). As a
18- // result, any input buffer larger than 1232 will abort deserialization and
19- // return `InstructionError::InvalidInstructionData`.
27+ // the input buffer at `MAX_INPUT_LEN` (1232 ). As a result, any input buffer
28+ // larger than `MAX_INPUT_LEN` will abort deserialization and return
29+ // `InstructionError::InvalidInstructionData`.
2030//
2131// Howevever, since `ConfigKeys` contains a vector of `(Pubkey, bool)`, the
2232// `limited_deserialize` method will still read the vector's length and attempt
@@ -26,19 +36,15 @@ use {
2636//
2737// To mitigate this memory issue, the BPF version of the Config program has
2838// been designed to "peek" the length value, and ensure it cannot allocate a
29- // vector that would otherwise violate the input buffer length restriction of
30- // 1232.
31- //
32- // Taking the maximum input length of 1232 and subtracting (up to) 3 bytes for
33- // the `ShortU16`, then dividing that by the size of a `(Pubkey, bool)` entry
34- // (33), we get a maximum vector size of 37. A `ShortU16` value for 37 fits in
35- // just one byte (`[0x25]`), so this function can simply check the first
36- // provided byte.
39+ // vector that would otherwise violate the input buffer length restriction.
40+ // Since a `ShortU16` value for `MAX_VECTOR_LEN` fits in just one byte, we can
41+ // simply peek the first byte before attempting deserialization.
3742fn safe_deserialize_config_keys ( input : & [ u8 ] ) -> Result < ConfigKeys , ProgramError > {
3843 match input. first ( ) {
39- Some ( first_byte) if * first_byte <= 0x25 => {
44+ Some ( first_byte) if * first_byte as usize <= MAX_VECTOR_LEN => {
4045 solana_program:: program_utils:: limited_deserialize :: < ConfigKeys > (
41- input, 1232 , // [Core BPF]: See `solana_sdk::packet::PACKET_DATA_SIZE`
46+ input,
47+ MAX_INPUT_LEN as u64 ,
4248 )
4349 . map_err ( |_| ProgramError :: InvalidInstructionData )
4450 }
0 commit comments