Reject modifications to userdata if not owned by the program

This commit is contained in:
Greg Fitzgerald 2019-02-15 11:55:32 -07:00
parent 77ea4cd285
commit 5541eedcc4
2 changed files with 21 additions and 3 deletions

View File

@ -59,6 +59,7 @@ fn verify_instruction(
program_id: &Pubkey,
pre_program_id: &Pubkey,
pre_tokens: u64,
pre_userdata: &[u8],
account: &Account,
) -> Result<(), ProgramError> {
// Verify the transaction
@ -71,6 +72,13 @@ fn verify_instruction(
if *program_id != account.owner && pre_tokens > account.tokens {
return Err(ProgramError::ExternalAccountTokenSpend);
}
// For accounts unassigned to the program, the userdata may not change.
if *program_id != account.owner
&& !system_program::check_id(&program_id)
&& pre_userdata != &account.userdata[..]
{
return Err(ProgramError::ExternalAccountUserdataModified);
}
Ok(())
}
@ -91,7 +99,7 @@ fn execute_instruction(
let pre_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();
let pre_data: Vec<_> = program_accounts
.iter_mut()
.map(|a| (a.owner, a.tokens))
.map(|a| (a.owner, a.tokens, a.userdata.clone()))
.collect();
process_instruction(
@ -103,9 +111,16 @@ fn execute_instruction(
)?;
// Verify the instruction
for ((pre_program_id, pre_tokens), post_account) in pre_data.iter().zip(program_accounts.iter())
for ((pre_program_id, pre_tokens, pre_userdata), post_account) in
pre_data.iter().zip(program_accounts.iter())
{
verify_instruction(&program_id, pre_program_id, *pre_tokens, post_account)?;
verify_instruction(
&program_id,
pre_program_id,
*pre_tokens,
pre_userdata,
post_account,
)?;
}
// The total sum of all the tokens in all the accounts cannot change.
let post_total: u64 = program_accounts.iter().map(|a| a.tokens).sum();

View File

@ -25,6 +25,9 @@ pub enum ProgramError {
/// Program spent the tokens of an account that doesn't belong to it
ExternalAccountTokenSpend,
/// Program modified the userdata of an account that doesn't belong to it
ExternalAccountUserdataModified,
/// An account's userdata contents was invalid
InvalidUserdata,