@@ -6,7 +6,7 @@ use pinocchio::{
66use token_interface:: {
77 error:: TokenError ,
88 instruction:: AuthorityType ,
9- state:: { account:: Account , load_mut , mint:: Mint , RawType } ,
9+ state:: { account:: Account , load , load_mut_unchecked , mint:: Mint , RawType } ,
1010} ;
1111
1212use super :: validate_owner;
@@ -27,18 +27,24 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8])
2727 } ;
2828
2929 if account_info. data_len ( ) == Account :: LEN {
30- // SAFETY: there are no other active borrows of the `account` data.
31- let account = unsafe { load_mut :: < Account > ( account_info. borrow_mut_data_unchecked ( ) ) ? } ;
30+ // SAFETY: immutable borrow of `account_info` account data. The `load`
31+ // validates that the account is initialized.
32+ let account = unsafe { load :: < Account > ( account_info. borrow_data_unchecked ( ) ) ? } ;
3233
3334 if account. is_frozen ( ) {
3435 return Err ( TokenError :: AccountFrozen . into ( ) ) ;
3536 }
3637
3738 match authority_type {
3839 AuthorityType :: AccountOwner => {
39- // TODO: Can account and authority be the same?
4040 validate_owner ( & account. owner , authority_info, remaning) ?;
4141
42+ // SAFETY: single mutable borrow of `account_info` account data. The
43+ // `account_info` is guaranteed to the initialized.
44+ let account = unsafe {
45+ load_mut_unchecked :: < Account > ( account_info. borrow_mut_data_unchecked ( ) ) ?
46+ } ;
47+
4248 if let Some ( authority) = new_authority {
4349 account. owner = * authority;
4450 } else {
@@ -54,9 +60,15 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8])
5460 }
5561 AuthorityType :: CloseAccount => {
5662 let authority = account. close_authority ( ) . unwrap_or ( & account. owner ) ;
57- // TODO: Can account and authority be the same?
63+
5864 validate_owner ( authority, authority_info, remaning) ?;
5965
66+ // SAFETY: single mutable borrow of `account_info` account data. The
67+ // `account_info` is guaranteed to the initialized.
68+ let account = unsafe {
69+ load_mut_unchecked :: < Account > ( account_info. borrow_mut_data_unchecked ( ) ) ?
70+ } ;
71+
6072 if let Some ( authority) = new_authority {
6173 account. set_close_authority ( authority) ;
6274 } else {
@@ -68,17 +80,24 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8])
6880 }
6981 }
7082 } else if account_info. data_len ( ) == Mint :: LEN {
71- // SAFETY: there are no other active borrows of the `account` data.
72- let mint = unsafe { load_mut :: < Mint > ( account_info. borrow_mut_data_unchecked ( ) ) ? } ;
83+ // SAFETY: immutable borrow of `account_info` account data. The `load`
84+ // validates that the mint is initialized.
85+ let mint = unsafe { load :: < Mint > ( account_info. borrow_mut_data_unchecked ( ) ) ? } ;
7386
7487 match authority_type {
7588 AuthorityType :: MintTokens => {
7689 // Once a mint's supply is fixed, it cannot be undone by setting a new
7790 // mint_authority.
7891 let mint_authority = mint. mint_authority ( ) . ok_or ( TokenError :: FixedSupply ) ?;
79- // TODO: Can account and authority be the same?
92+
8093 validate_owner ( mint_authority, authority_info, remaning) ?;
8194
95+ // SAFETY: single mutable borrow of `account_info` account data. The
96+ // `account_info` is guaranteed to the initialized.
97+ let mint = unsafe {
98+ load_mut_unchecked :: < Mint > ( account_info. borrow_mut_data_unchecked ( ) ) ?
99+ } ;
100+
82101 if let Some ( authority) = new_authority {
83102 mint. set_mint_authority ( authority) ;
84103 } else {
@@ -91,9 +110,15 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8])
91110 let freeze_authority = mint
92111 . freeze_authority ( )
93112 . ok_or ( TokenError :: MintCannotFreeze ) ?;
94- // TODO: Can account and authority be the same?
113+
95114 validate_owner ( freeze_authority, authority_info, remaning) ?;
96115
116+ // SAFETY: single mutable borrow of `account_info` account data. The
117+ // `account_info` is guaranteed to the initialized.
118+ let mint = unsafe {
119+ load_mut_unchecked :: < Mint > ( account_info. borrow_mut_data_unchecked ( ) ) ?
120+ } ;
121+
97122 if let Some ( authority) = new_authority {
98123 mint. set_freeze_authority ( authority) ;
99124 } else {
@@ -123,7 +148,7 @@ impl SetAuthority<'_> {
123148 // The minimum expected size of the instruction data.
124149 // - authority_type (1 byte)
125150 // - option + new_authority (1 byte + 32 bytes)
126- if bytes. len ( ) < 2 {
151+ if bytes. len ( ) < 2 || ( bytes [ 1 ] == 1 && bytes . len ( ) < 34 ) {
127152 return Err ( ProgramError :: InvalidInstructionData ) ;
128153 }
129154
@@ -135,11 +160,13 @@ impl SetAuthority<'_> {
135160
136161 #[ inline( always) ]
137162 pub fn authority_type ( & self ) -> Result < AuthorityType , ProgramError > {
163+ // SAFETY: `bytes` length is validated in `try_from_bytes`.
138164 unsafe { AuthorityType :: from ( * self . raw ) }
139165 }
140166
141167 #[ inline( always) ]
142168 pub fn new_authority ( & self ) -> Option < & Pubkey > {
169+ // SAFETY: `bytes` length is validated in `try_from_bytes`.
143170 unsafe {
144171 if * self . raw . add ( 1 ) == 0 {
145172 Option :: None
0 commit comments