@@ -1033,6 +1033,12 @@ pub fn test_process_transfer(
10331033 let old_src_delgated_amount = src_old. delegated_amount ( ) ;
10341034 let maybe_multisig_is_initialised = None ; // Value set to `None` since authority is an account
10351035
1036+ #[ cfg( feature = "assumptions" ) ]
1037+ // avoids potential overflow in destination account. assuming global supply bound by u64
1038+ if accounts[ 0 ] != accounts[ 1 ] && dst_initial_amount. checked_add ( amount) . is_none ( ) {
1039+ return Err ( ProgramError :: Custom ( 99 ) ) ;
1040+ }
1041+
10361042 //-Process Instruction-----------------------------------------------------
10371043 let result = process_transfer ( accounts, instruction_data) ;
10381044
@@ -1121,12 +1127,16 @@ pub fn test_process_transfer(
11211127 } else if accounts[ 0 ] != accounts[ 1 ]
11221128 && amount != 0
11231129 && src_new. is_native ( )
1124- && u64 :: MAX - amount < dst_initial_lamports
1130+ && dst_initial_lamports. checked_add ( amount ) . is_none ( )
11251131 {
11261132 // Not sure how to fund native mint
11271133 assert_eq ! ( result, Err ( ProgramError :: Custom ( 14 ) ) ) ;
11281134 return result;
1129- } else if accounts[ 0 ] != accounts[ 1 ] && amount != 0 {
1135+ }
1136+
1137+ assert ! ( result. is_ok( ) ) ;
1138+
1139+ if accounts[ 0 ] != accounts[ 1 ] && amount != 0 {
11301140 assert_eq ! ( src_new. amount( ) , src_initial_amount - amount) ;
11311141 assert_eq ! (
11321142 get_account( & accounts[ 1 ] ) . amount( ) ,
@@ -1139,8 +1149,6 @@ pub fn test_process_transfer(
11391149 }
11401150 }
11411151
1142- assert ! ( result. is_ok( ) ) ;
1143-
11441152 // Delegate updates
11451153 if old_src_delgate == Some ( * accounts[ 2 ] . key ( ) ) && accounts[ 0 ] != accounts[ 1 ] {
11461154 assert_eq ! ( src_new. delegated_amount( ) , old_src_delgated_amount - amount) ;
@@ -1328,6 +1336,18 @@ pub fn test_process_mint_to(
13281336 let dst_init_state = dst_old. account_state ( ) ;
13291337 let maybe_multisig_is_initialised = None ; // Value set to `None` since authority is an account
13301338
1339+ #[ cfg( feature = "assumptions" ) ]
1340+ {
1341+ // Do not execute if adding to the account balance would overflow.
1342+ // shared::mint_to.rs,L68 is based on the assumption that initial_amount <=
1343+ // mint.supply and therefore cannot overflow because the minting itself
1344+ // would already error out.
1345+ let amount = unsafe { u64:: from_le_bytes ( * ( instruction_data. as_ptr ( ) as * const [ u8 ; 8 ] ) ) } ;
1346+ if initial_amount. checked_add ( amount) . is_none ( ) {
1347+ return Err ( ProgramError :: Custom ( 99 ) ) ;
1348+ }
1349+ }
1350+
13311351 //-Process Instruction-----------------------------------------------------
13321352 let result = process_mint_to ( accounts, instruction_data) ;
13331353
@@ -1392,7 +1412,7 @@ pub fn test_process_mint_to(
13921412 } else if amount == 0 && accounts[ 1 ] . owner ( ) != & pinocchio_token_interface:: program:: ID {
13931413 assert_eq ! ( result, Err ( ProgramError :: IncorrectProgramId ) ) ;
13941414 return result;
1395- } else if amount != 0 && u64 :: MAX - amount < initial_supply {
1415+ } else if amount != 0 && amount. checked_add ( initial_supply) . is_none ( ) {
13961416 assert_eq ! ( result, Err ( ProgramError :: Custom ( 14 ) ) ) ;
13971417 return result;
13981418 }
@@ -1538,6 +1558,13 @@ pub fn test_process_burn(accounts: &[AccountInfo; 3], instruction_data: &[u8; 8]
15381558 let mint_owner = * accounts[ 1 ] . owner ( ) ;
15391559 let maybe_multisig_is_initialised = None ; // Value set to `None` since authority is an account
15401560
1561+ #[ cfg( feature = "assumptions" ) ]
1562+ // accoutn.amount() <= mint.supply(), account.delegated_amount() <= account.amount()
1563+ // otherwise processing could lead to overflows, see processor::shared::burn,L83
1564+ if !( src_init_amount <= mint_init_supply && old_src_delgated_amount <= src_init_amount) {
1565+ return Err ( ProgramError :: Custom ( 99 ) ) ;
1566+ }
1567+
15411568 //-Process Instruction-----------------------------------------------------
15421569 let result = process_burn ( accounts, instruction_data) ;
15431570
@@ -1788,7 +1815,7 @@ pub fn test_process_close_account(accounts: &[AccountInfo; 3]) -> ProgramResult
17881815 } else if accounts[ 1 ] . key ( ) != & INCINERATOR_ID {
17891816 assert_eq ! ( result, Err ( ProgramError :: InvalidAccountData ) ) ;
17901817 return result;
1791- } else if u64 :: MAX - src_init_lamports < dst_init_lamports {
1818+ } else if dst_init_lamports. checked_add ( src_init_lamports ) . is_none ( ) {
17921819 assert_eq ! ( result, Err ( ProgramError :: Custom ( 14 ) ) ) ;
17931820 return result;
17941821 }
@@ -1914,6 +1941,12 @@ pub fn test_process_transfer_checked(
19141941 let mint_initialised = get_mint ( & accounts[ 1 ] ) . is_initialized ( ) ;
19151942 let maybe_multisig_is_initialised = None ; // Value set to `None` since authority is an account
19161943
1944+ #[ cfg( feature = "assumptions" ) ]
1945+ // avoids potential overflow in destination account. assuming global supply bound by u64
1946+ if accounts[ 0 ] != accounts[ 1 ] && dst_initial_amount. checked_add ( amount) . is_none ( ) {
1947+ return Err ( ProgramError :: Custom ( 99 ) ) ;
1948+ }
1949+
19171950 //-Process Instruction-----------------------------------------------------
19181951 let result = process_transfer_checked ( accounts, instruction_data) ;
19191952
@@ -2008,12 +2041,15 @@ pub fn test_process_transfer_checked(
20082041 {
20092042 assert_eq ! ( result, Err ( ProgramError :: IncorrectProgramId ) ) ;
20102043 return result;
2011- } else if accounts[ 0 ] != accounts[ 2 ] && amount != 0 {
2044+ }
2045+ assert ! ( result. is_ok( ) ) ;
2046+
2047+ if accounts[ 0 ] != accounts[ 2 ] && amount != 0 {
20122048 if src_new. is_native ( ) && src_initial_lamports < amount {
20132049 // Not sure how to fund native mint
20142050 assert_eq ! ( result, Err ( ProgramError :: Custom ( 14 ) ) ) ;
20152051 return result;
2016- } else if src_new. is_native ( ) && u64 :: MAX - amount < dst_initial_lamports {
2052+ } else if src_new. is_native ( ) && dst_initial_lamports. checked_add ( amount ) . is_none ( ) {
20172053 // Not sure how to fund native mint
20182054 assert_eq ! ( result, Err ( ProgramError :: Custom ( 14 ) ) ) ;
20192055 return result;
@@ -2031,7 +2067,6 @@ pub fn test_process_transfer_checked(
20312067 }
20322068 }
20332069
2034- assert ! ( result. is_ok( ) ) ;
20352070 // Delegate updates
20362071 if old_src_delgate == Some ( * accounts[ 3 ] . key ( ) ) && accounts[ 0 ] != accounts[ 2 ] {
20372072 assert_eq ! ( src_new. delegated_amount( ) , old_src_delgated_amount - amount) ;
@@ -2242,6 +2277,13 @@ pub fn test_process_burn_checked(
22422277 let mint_owner = * accounts[ 1 ] . owner ( ) ;
22432278 let maybe_multisig_is_initialised = None ; // Value set to `None` since authority is an account
22442279
2280+ #[ cfg( feature = "assumptions" ) ]
2281+ // accoutn.amount() <= mint.supply(), account.delegated_amount() <= account.amount()
2282+ // otherwise processing could lead to overflows, see processor::shared::burn,L83
2283+ if !( src_init_amount <= mint_init_supply && old_src_delgated_amount <= src_init_amount) {
2284+ return Err ( ProgramError :: Custom ( 99 ) ) ;
2285+ }
2286+
22452287 //-Process Instruction-----------------------------------------------------
22462288 let result = process_burn_checked ( accounts, instruction_data) ;
22472289
@@ -3902,6 +3944,18 @@ fn test_process_mint_to_checked(
39023944 let dst_init_state = dst_old. account_state ( ) ;
39033945 let maybe_multisig_is_initialised = None ; // Value set to `None` since authority is an account
39043946
3947+ #[ cfg( feature = "assumptions" ) ]
3948+ {
3949+ // Do not execute if adding to the account balance would overflow.
3950+ // shared::mint_to.rs,L68 is based on the assumption that initial_amount <=
3951+ // mint.supply and therefore cannot overflow because the minting itself
3952+ // would already error out.
3953+ let amount = unsafe { u64:: from_le_bytes ( * ( instruction_data. as_ptr ( ) as * const [ u8 ; 8 ] ) ) } ;
3954+ if initial_amount. checked_add ( amount) . is_none ( ) {
3955+ return Err ( ProgramError :: Custom ( 99 ) ) ;
3956+ }
3957+ }
3958+
39053959 //-Process Instruction-----------------------------------------------------
39063960 let result = process_mint_to_checked ( accounts, instruction_data) ;
39073961
@@ -3970,7 +4024,7 @@ fn test_process_mint_to_checked(
39704024 } else if amount == 0 && accounts[ 1 ] . owner ( ) != & pinocchio_token_interface:: program:: ID {
39714025 assert_eq ! ( result, Err ( ProgramError :: IncorrectProgramId ) ) ;
39724026 return result;
3973- } else if amount != 0 && u64 :: MAX - amount < initial_supply {
4027+ } else if amount != 0 && initial_supply. checked_add ( amount ) . is_none ( ) {
39744028 assert_eq ! ( result, Err ( ProgramError :: Custom ( 14 ) ) ) ;
39754029 return result;
39764030 }
@@ -4446,15 +4500,18 @@ fn test_process_withdraw_excess_lamports_account(accounts: &[AccountInfo; 3]) ->
44464500 if src_init_lamports < minimum_balance {
44474501 assert_eq ! ( result, Err ( ProgramError :: Custom ( 0 ) ) ) ;
44484502 return result;
4449- } else if u64:: MAX - src_init_lamports + minimum_balance < dst_init_lamports {
4503+ } else if dst_init_lamports
4504+ . checked_add ( src_init_lamports - minimum_balance)
4505+ . is_none ( )
4506+ {
44504507 assert_eq ! ( result, Err ( ProgramError :: Custom ( 0 ) ) ) ;
44514508 return result;
44524509 }
44534510
44544511 assert_eq ! ( accounts[ 0 ] . lamports( ) , minimum_balance) ;
44554512 assert_eq ! (
44564513 accounts[ 1 ] . lamports( ) ,
4457- dst_init_lamports + src_init_lamports - minimum_balance
4514+ dst_init_lamports + ( src_init_lamports - minimum_balance)
44584515 ) ;
44594516 assert ! ( result. is_ok( ) )
44604517 }
@@ -4597,15 +4654,18 @@ fn test_process_withdraw_excess_lamports_mint(accounts: &[AccountInfo; 3]) -> Pr
45974654 } else if src_init_lamports < minimum_balance {
45984655 assert_eq ! ( result, Err ( ProgramError :: Custom ( 0 ) ) ) ;
45994656 return result;
4600- } else if u64:: MAX - src_init_lamports + minimum_balance < dst_init_lamports {
4657+ } else if dst_init_lamports
4658+ . checked_add ( src_init_lamports - minimum_balance)
4659+ . is_none ( )
4660+ {
46014661 assert_eq ! ( result, Err ( ProgramError :: Custom ( 0 ) ) ) ;
46024662 return result;
46034663 }
46044664
46054665 assert_eq ! ( accounts[ 0 ] . lamports( ) , minimum_balance) ;
46064666 assert_eq ! (
46074667 accounts[ 1 ] . lamports( ) ,
4608- dst_init_lamports + src_init_lamports - minimum_balance
4668+ dst_init_lamports + ( src_init_lamports - minimum_balance)
46094669 ) ;
46104670 assert ! ( result. is_ok( ) )
46114671 }
@@ -4739,15 +4799,18 @@ fn test_process_withdraw_excess_lamports_multisig(accounts: &[AccountInfo; 3]) -
47394799 if src_init_lamports < minimum_balance {
47404800 assert_eq ! ( result, Err ( ProgramError :: Custom ( 0 ) ) ) ;
47414801 return result;
4742- } else if u64:: MAX - src_init_lamports + minimum_balance < dst_init_lamports {
4802+ } else if dst_init_lamports
4803+ . checked_add ( src_init_lamports - minimum_balance)
4804+ . is_none ( )
4805+ {
47434806 assert_eq ! ( result, Err ( ProgramError :: Custom ( 0 ) ) ) ;
47444807 return result;
47454808 }
47464809
47474810 assert_eq ! ( accounts[ 0 ] . lamports( ) , minimum_balance) ;
47484811 assert_eq ! (
47494812 accounts[ 1 ] . lamports( ) ,
4750- dst_init_lamports + src_init_lamports - minimum_balance
4813+ dst_init_lamports + ( src_init_lamports - minimum_balance)
47514814 ) ;
47524815 assert ! ( result. is_ok( ) )
47534816 }
0 commit comments