cpi: fix capacity check in update_caller_account (#34064)
reserve(additional) reserves additional bytes on top of the current _length_ not capacity. Before this fix we could potentially reserve less capacity than required.
This commit is contained in:
parent
7fd13c0cd2
commit
d009d7304a
|
@ -1461,7 +1461,8 @@ fn update_caller_account(
|
||||||
// invalid address.
|
// invalid address.
|
||||||
let min_capacity = caller_account.original_data_len;
|
let min_capacity = caller_account.original_data_len;
|
||||||
if callee_account.capacity() < min_capacity {
|
if callee_account.capacity() < min_capacity {
|
||||||
callee_account.reserve(min_capacity.saturating_sub(callee_account.capacity()))?;
|
callee_account
|
||||||
|
.reserve(min_capacity.saturating_sub(callee_account.get_data().len()))?;
|
||||||
zero_all_mapped_spare_capacity = true;
|
zero_all_mapped_spare_capacity = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1288,6 +1288,33 @@ fn process_instruction(
|
||||||
},
|
},
|
||||||
&vec![0; original_data_len - new_len]
|
&vec![0; original_data_len - new_len]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Realloc to [0xFC; 2]
|
||||||
|
invoke(
|
||||||
|
&create_instruction(
|
||||||
|
*callee_program_id,
|
||||||
|
&[
|
||||||
|
(accounts[ARGUMENT_INDEX].key, true, false),
|
||||||
|
(callee_program_id, false, false),
|
||||||
|
],
|
||||||
|
vec![0xFC; 2],
|
||||||
|
),
|
||||||
|
accounts,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Check that [2..20] is zeroed
|
||||||
|
let new_len = account.data_len();
|
||||||
|
assert_eq!(&*account.data.borrow(), &[0xFC; 2]);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe {
|
||||||
|
slice::from_raw_parts(
|
||||||
|
account.data.borrow().as_ptr().add(new_len),
|
||||||
|
original_data_len - new_len,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
&vec![0; original_data_len - new_len]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
TEST_WRITE_ACCOUNT => {
|
TEST_WRITE_ACCOUNT => {
|
||||||
msg!("TEST_WRITE_ACCOUNT");
|
msg!("TEST_WRITE_ACCOUNT");
|
||||||
|
|
|
@ -4420,12 +4420,18 @@ fn test_cpi_change_account_data_memory_allocation() {
|
||||||
|
|
||||||
// Test changing the account data both in place and by changing the
|
// Test changing the account data both in place and by changing the
|
||||||
// underlying vector. CPI will have to detect the vector change and
|
// underlying vector. CPI will have to detect the vector change and
|
||||||
// update the corresponding memory region. In both cases CPI will have
|
// update the corresponding memory region. In all cases CPI will have
|
||||||
// to zero the spare bytes correctly.
|
// to zero the spare bytes correctly.
|
||||||
if instruction_data[0] == 0xFE {
|
match instruction_data[0] {
|
||||||
account.set_data(instruction_data.to_vec());
|
0xFE => account.set_data(instruction_data.to_vec()),
|
||||||
} else {
|
0xFD => account.set_data_from_slice(instruction_data),
|
||||||
account.set_data_from_slice(instruction_data);
|
0xFC => {
|
||||||
|
// Exercise the update_caller_account capacity check where account len != capacity.
|
||||||
|
let mut data = instruction_data.to_vec();
|
||||||
|
data.reserve_exact(1);
|
||||||
|
account.set_data(data)
|
||||||
|
}
|
||||||
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue