Skip to content

Commit

Permalink
programs/sbf: add tests for verification of SolAccountInfo pointers too
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrod committed Jul 18, 2023
1 parent c01ffe1 commit 291e0a0
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 21 deletions.
73 changes: 73 additions & 0 deletions programs/sbf/c/src/invoke/invoke.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
48 changes: 27 additions & 21 deletions programs/sbf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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:?}"
);
}
}
}

Expand Down

0 comments on commit 291e0a0

Please sign in to comment.