1
1
use byteorder:: { ByteOrder , LittleEndian , WriteBytesExt } ;
2
2
use solana_sdk:: {
3
- account:: KeyedAccount , bpf_loader_deprecated, instruction:: InstructionError , pubkey:: Pubkey ,
3
+ account:: KeyedAccount , bpf_loader_deprecated, entrypoint:: MAX_PERMITTED_DATA_INCREASE ,
4
+ instruction:: InstructionError , pubkey:: Pubkey ,
4
5
} ;
5
6
use std:: {
6
7
io:: prelude:: * ,
7
- mem:: { self , align_of } ,
8
+ mem:: { align_of , size_of } ,
8
9
} ;
9
10
10
11
/// Look for a duplicate account and return its position if found
@@ -47,7 +48,7 @@ pub fn serialize_parameters_unaligned(
47
48
keyed_accounts : & [ KeyedAccount ] ,
48
49
instruction_data : & [ u8 ] ,
49
50
) -> Result < Vec < u8 > , InstructionError > {
50
- assert_eq ! ( 32 , mem :: size_of:: <Pubkey >( ) ) ;
51
+ assert_eq ! ( 32 , size_of:: <Pubkey >( ) ) ;
51
52
52
53
let mut v: Vec < u8 > = Vec :: new ( ) ;
53
54
v. write_u64 :: < LittleEndian > ( keyed_accounts. len ( ) as u64 )
@@ -84,29 +85,29 @@ pub fn deserialize_parameters_unaligned(
84
85
keyed_accounts : & [ KeyedAccount ] ,
85
86
buffer : & [ u8 ] ,
86
87
) -> Result < ( ) , InstructionError > {
87
- assert_eq ! ( 32 , mem :: size_of:: <Pubkey >( ) ) ;
88
+ assert_eq ! ( 32 , size_of:: <Pubkey >( ) ) ;
88
89
89
- let mut start = mem :: size_of :: < u64 > ( ) ; // number of accounts
90
+ let mut start = size_of :: < u64 > ( ) ; // number of accounts
90
91
for ( i, keyed_account) in keyed_accounts. iter ( ) . enumerate ( ) {
91
92
let ( is_dup, _) = is_dup ( & keyed_accounts[ ..i] , keyed_account) ;
92
93
start += 1 ; // is_dup
93
94
if !is_dup {
94
- start += mem :: size_of :: < u8 > ( ) ; // is_signer
95
- start += mem :: size_of :: < u8 > ( ) ; // is_writable
96
- start += mem :: size_of :: < Pubkey > ( ) ; // pubkey
95
+ start += size_of :: < u8 > ( ) ; // is_signer
96
+ start += size_of :: < u8 > ( ) ; // is_writable
97
+ start += size_of :: < Pubkey > ( ) ; // pubkey
97
98
keyed_account. try_account_ref_mut ( ) ?. lamports =
98
99
LittleEndian :: read_u64 ( & buffer[ start..] ) ;
99
- start += mem :: size_of :: < u64 > ( ) // lamports
100
- + mem :: size_of :: < u64 > ( ) ; // data length
100
+ start += size_of :: < u64 > ( ) // lamports
101
+ + size_of :: < u64 > ( ) ; // data length
101
102
let end = start + keyed_account. data_len ( ) ?;
102
103
keyed_account
103
104
. try_account_ref_mut ( ) ?
104
105
. data
105
106
. clone_from_slice ( & buffer[ start..end] ) ;
106
107
start += keyed_account. data_len ( ) ? // data
107
- + mem :: size_of :: < Pubkey > ( ) // owner
108
- + mem :: size_of :: < u8 > ( ) // executable
109
- + mem :: size_of :: < u64 > ( ) ; // rent_epoch
108
+ + size_of :: < Pubkey > ( ) // owner
109
+ + size_of :: < u8 > ( ) // executable
110
+ + size_of :: < u64 > ( ) ; // rent_epoch
110
111
}
111
112
}
112
113
Ok ( ( ) )
@@ -117,14 +118,12 @@ pub fn serialize_parameters_aligned(
117
118
keyed_accounts : & [ KeyedAccount ] ,
118
119
instruction_data : & [ u8 ] ,
119
120
) -> Result < Vec < u8 > , InstructionError > {
120
- assert_eq ! ( 32 , mem :: size_of:: <Pubkey >( ) ) ;
121
+ assert_eq ! ( 32 , size_of:: <Pubkey >( ) ) ;
121
122
122
- // TODO use with capacity would be nice, but don't know account data sizes...
123
123
let mut v: Vec < u8 > = Vec :: new ( ) ;
124
124
v. write_u64 :: < LittleEndian > ( keyed_accounts. len ( ) as u64 )
125
125
. unwrap ( ) ;
126
126
127
- // TODO panic?
128
127
if v. as_ptr ( ) . align_offset ( align_of :: < u128 > ( ) ) != 0 {
129
128
panic ! ( ) ;
130
129
}
@@ -148,7 +147,9 @@ pub fn serialize_parameters_aligned(
148
147
. unwrap ( ) ;
149
148
v. write_all ( & keyed_account. try_account_ref ( ) ?. data ) . unwrap ( ) ;
150
149
v. resize (
151
- v. len ( ) + ( v. len ( ) as * const u8 ) . align_offset ( align_of :: < u128 > ( ) ) ,
150
+ v. len ( )
151
+ + MAX_PERMITTED_DATA_INCREASE
152
+ + ( v. len ( ) as * const u8 ) . align_offset ( align_of :: < u128 > ( ) ) ,
152
153
0 ,
153
154
) ;
154
155
v. write_u64 :: < LittleEndian > ( keyed_account. rent_epoch ( ) ? as u64 )
@@ -166,33 +167,39 @@ pub fn deserialize_parameters_aligned(
166
167
keyed_accounts : & [ KeyedAccount ] ,
167
168
buffer : & [ u8 ] ,
168
169
) -> Result < ( ) , InstructionError > {
169
- assert_eq ! ( 32 , mem :: size_of:: <Pubkey >( ) ) ;
170
+ assert_eq ! ( 32 , size_of:: <Pubkey >( ) ) ;
170
171
171
- let mut start = mem :: size_of :: < u64 > ( ) ; // number of accounts
172
+ let mut start = size_of :: < u64 > ( ) ; // number of accounts
172
173
for ( i, keyed_account) in keyed_accounts. iter ( ) . enumerate ( ) {
173
174
let ( is_dup, _) = is_dup ( & keyed_accounts[ ..i] , keyed_account) ;
174
- start += 1 ; // is_dup
175
- if !is_dup {
176
- start += mem:: size_of :: < u8 > ( ) // is_signer
177
- + mem:: size_of :: < u8 > ( ) // is_writable
178
- + mem:: size_of :: < u8 > ( ) // executable
179
- + 4 // padding
180
- + mem:: size_of :: < Pubkey > ( ) // pubkey
181
- + mem:: size_of :: < Pubkey > ( ) ; // owner
182
- keyed_account. try_account_ref_mut ( ) ?. lamports =
183
- LittleEndian :: read_u64 ( & buffer[ start..] ) ;
184
- start += mem:: size_of :: < u64 > ( ) // lamports
185
- + mem:: size_of :: < u64 > ( ) ; // data length
186
- let end = start + keyed_account. data_len ( ) ?;
187
- keyed_account
188
- . try_account_ref_mut ( ) ?
189
- . data
190
- . clone_from_slice ( & buffer[ start..end] ) ;
191
- start += keyed_account. data_len ( ) ?; // data
192
- start += ( start as * const u8 ) . align_offset ( align_of :: < u128 > ( ) ) ;
193
- start += mem:: size_of :: < u64 > ( ) ; // rent_epoch
175
+ start += size_of :: < u8 > ( ) ; // position
176
+ if is_dup {
177
+ start += 7 ; // padding to 64-bit aligned
194
178
} else {
195
- start += 7 ; // padding
179
+ let mut account = keyed_account. try_account_ref_mut ( ) ?;
180
+ start += size_of :: < u8 > ( ) // is_signer
181
+ + size_of :: < u8 > ( ) // is_writable
182
+ + size_of :: < u8 > ( ) // executable
183
+ + 4 // padding to 128-bit aligned
184
+ + size_of :: < Pubkey > ( ) ; // key
185
+ account. owner = Pubkey :: new ( & buffer[ start..start + size_of :: < Pubkey > ( ) ] ) ;
186
+ start += size_of :: < Pubkey > ( ) ; // owner
187
+ account. lamports = LittleEndian :: read_u64 ( & buffer[ start..] ) ;
188
+ start += size_of :: < u64 > ( ) ; // lamports
189
+ let pre_len = account. data . len ( ) ;
190
+ let post_len = LittleEndian :: read_u64 ( & buffer[ start..] ) as usize ;
191
+ start += size_of :: < u64 > ( ) ; // data length
192
+ let mut data_end = start + pre_len;
193
+ if post_len != pre_len
194
+ && ( post_len. saturating_sub ( pre_len) ) <= MAX_PERMITTED_DATA_INCREASE
195
+ {
196
+ account. data . resize ( post_len, 0 ) ;
197
+ data_end = start + post_len;
198
+ }
199
+ account. data . clone_from_slice ( & buffer[ start..data_end] ) ;
200
+ start += pre_len + MAX_PERMITTED_DATA_INCREASE ; // data
201
+ start += ( start as * const u8 ) . align_offset ( align_of :: < u128 > ( ) ) ;
202
+ start += size_of :: < u64 > ( ) ; // rent_epoch
196
203
}
197
204
}
198
205
Ok ( ( ) )
@@ -206,7 +213,6 @@ mod tests {
206
213
} ;
207
214
use std:: {
208
215
cell:: RefCell ,
209
- mem:: size_of,
210
216
rc:: Rc ,
211
217
// Hide Result from bindgen gets confused about generics in non-generic type declarations
212
218
slice:: { from_raw_parts, from_raw_parts_mut} ,
0 commit comments