diff --git a/programs/sbf/c/src/invoke/invoke.c b/programs/sbf/c/src/invoke/invoke.c index 4cb038cc7f6950..1ff4e6b69a096c 100644 --- a/programs/sbf/c/src/invoke/invoke.c +++ b/programs/sbf/c/src/invoke/invoke.c @@ -31,6 +31,12 @@ static const uint8_t TEST_RETURN_DATA_TOO_LARGE = 18; static const uint8_t TEST_DUPLICATE_PRIVILEGE_ESCALATION_SIGNER = 19; static const uint8_t TEST_DUPLICATE_PRIVILEGE_ESCALATION_WRITABLE = 20; static const uint8_t TEST_MAX_ACCOUNT_INFOS_EXCEEDED = 21; +// TEST_CPI_INVALID_* must match the definitions in +// https://github.com/solana-labs/solana/blob/master/programs/sbf/rust/invoke/src/instructions.rs +static const uint8_t TEST_CPI_INVALID_KEY_POINTER = 34; +static const uint8_t TEST_CPI_INVALID_OWNER_POINTER = 35; +static const uint8_t TEST_CPI_INVALID_LAMPORTS_POINTER = 36; +static const uint8_t TEST_CPI_INVALID_DATA_POINTER = 37; static const int MINT_INDEX = 0; static const int ARGUMENT_INDEX = 1; @@ -663,6 +669,73 @@ extern uint64_t entrypoint(const uint8_t *input) { sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)); break; } + case TEST_CPI_INVALID_KEY_POINTER: + { + sol_log("Test TEST_CPI_INVALID_KEY_POINTER"); + SolAccountMeta arguments[] = { + {accounts[ARGUMENT_INDEX].key, false, false}, + {accounts[INVOKED_ARGUMENT_INDEX].key, false, false}, + }; + uint8_t data[] = {}; + SolPubkey key = *accounts[ARGUMENT_INDEX].key; + accounts[ARGUMENT_INDEX].key = &key; + + const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key, + arguments, SOL_ARRAY_SIZE(arguments), + data, SOL_ARRAY_SIZE(data)}; + sol_invoke(&instruction, accounts, 4); + break; + } + case TEST_CPI_INVALID_LAMPORTS_POINTER: + { + sol_log("Test TEST_CPI_INVALID_LAMPORTS_POINTER"); + SolAccountMeta arguments[] = { + {accounts[ARGUMENT_INDEX].key, false, false}, + {accounts[INVOKED_ARGUMENT_INDEX].key, false, false}, + }; + uint8_t data[] = {}; + uint64_t lamports = *accounts[ARGUMENT_INDEX].lamports; + accounts[ARGUMENT_INDEX].lamports = &lamports; + + const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key, + arguments, SOL_ARRAY_SIZE(arguments), + data, SOL_ARRAY_SIZE(data)}; + sol_invoke(&instruction, accounts, 4); + break; + } + case TEST_CPI_INVALID_OWNER_POINTER: + { + sol_log("Test TEST_CPI_INVALID_OWNER_POINTER"); + SolAccountMeta arguments[] = { + {accounts[ARGUMENT_INDEX].key, false, false}, + {accounts[INVOKED_ARGUMENT_INDEX].key, false, false}, + }; + uint8_t data[] = {}; + SolPubkey owner = *accounts[ARGUMENT_INDEX].owner; + accounts[ARGUMENT_INDEX].owner = &owner; + + const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key, + arguments, SOL_ARRAY_SIZE(arguments), + data, SOL_ARRAY_SIZE(data)}; + sol_invoke(&instruction, accounts, 4); + break; + } + case TEST_CPI_INVALID_DATA_POINTER: + { + sol_log("Test TEST_CPI_INVALID_DATA_POINTER"); + SolAccountMeta arguments[] = { + {accounts[ARGUMENT_INDEX].key, false, false}, + {accounts[INVOKED_ARGUMENT_INDEX].key, false, false}, + }; + uint8_t data[] = {}; + accounts[ARGUMENT_INDEX].data = data; + + const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key, + arguments, SOL_ARRAY_SIZE(arguments), + data, SOL_ARRAY_SIZE(data)}; + sol_invoke(&instruction, accounts, 4); + break; + } default: sol_panic(); diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 6ca2cb8fc56091..49c52a700adda2 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -4468,6 +4468,9 @@ fn test_cpi_invalid_account_info_pointers() { let bank = Arc::new(bank); let mut bank_client = BankClient::new_shared(&bank); + let c_invoke_program_id = + load_program(&bank_client, &bpf_loader::id(), &mint_keypair, "invoke"); + let (bank, invoke_program_id) = load_program_and_advance_slot( &mut bank_client, &bpf_loader::id(), @@ -4481,30 +4484,33 @@ fn test_cpi_invalid_account_info_pointers() { AccountMeta::new(mint_pubkey, true), AccountMeta::new(account_keypair.pubkey(), false), AccountMeta::new_readonly(invoke_program_id, false), + AccountMeta::new_readonly(c_invoke_program_id, false), ]; - for ix in [ - TEST_CPI_INVALID_KEY_POINTER, - TEST_CPI_INVALID_LAMPORTS_POINTER, - TEST_CPI_INVALID_OWNER_POINTER, - TEST_CPI_INVALID_DATA_POINTER, - ] { - let account = AccountSharedData::new(42, 5, &invoke_program_id); - bank.store_account(&account_keypair.pubkey(), &account); - let instruction = Instruction::new_with_bytes( - invoke_program_id, - &[ix, 42, 42, 42], - account_metas.clone(), - ); + for invoke_program_id in [c_invoke_program_id] { + for ix in [ + TEST_CPI_INVALID_KEY_POINTER, + TEST_CPI_INVALID_LAMPORTS_POINTER, + TEST_CPI_INVALID_OWNER_POINTER, + TEST_CPI_INVALID_DATA_POINTER, + ] { + let account = AccountSharedData::new(42, 5, &invoke_program_id); + bank.store_account(&account_keypair.pubkey(), &account); + let instruction = Instruction::new_with_bytes( + invoke_program_id, + &[ix, 42, 42, 42], + account_metas.clone(), + ); - let message = Message::new(&[instruction], Some(&mint_pubkey)); - let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash()); - let (result, _, logs) = process_transaction_and_record_inner(&bank, tx); - assert!(result.is_err(), "{result:?}"); - assert!( - logs.iter().any(|log| log.contains("Invalid pointer")), - "{logs:?}" - ); + let message = Message::new(&[instruction], Some(&mint_pubkey)); + let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash()); + let (result, _, logs) = process_transaction_and_record_inner(&bank, tx); + assert!(result.is_err(), "{result:?}"); + assert!( + logs.iter().any(|log| log.contains("Invalid pointer")), + "{logs:?}" + ); + } } }