Limit CPI instruction size (#14317)
This commit is contained in:
@@ -12,6 +12,8 @@ static const uint8_t TEST_EMPTY_ACCOUNTS_SLICE = 5;
|
||||
static const uint8_t TEST_CAP_SEEDS = 6;
|
||||
static const uint8_t TEST_CAP_SIGNERS = 7;
|
||||
static const uint8_t TEST_ALLOC_ACCESS_VIOLATION = 8;
|
||||
static const uint8_t TEST_INSTRUCTION_DATA_TOO_LARGE = 9;
|
||||
static const uint8_t TEST_INSTRUCTION_META_TOO_LARGE = 10;
|
||||
|
||||
static const int MINT_INDEX = 0;
|
||||
static const int ARGUMENT_INDEX = 1;
|
||||
@@ -405,6 +407,36 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
|
||||
break;
|
||||
}
|
||||
case TEST_INSTRUCTION_DATA_TOO_LARGE: {
|
||||
sol_log("Test instruction data too large");
|
||||
SolAccountMeta arguments[] = {};
|
||||
uint8_t *data = sol_calloc(1500, 1);
|
||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
arguments, SOL_ARRAY_SIZE(arguments),
|
||||
data, 1500};
|
||||
const SolSignerSeeds signers_seeds[] = {};
|
||||
sol_assert(SUCCESS == sol_invoke_signed(
|
||||
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
|
||||
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
|
||||
|
||||
break;
|
||||
}
|
||||
case TEST_INSTRUCTION_META_TOO_LARGE: {
|
||||
sol_log("Test instruction meta too large");
|
||||
SolAccountMeta *arguments = sol_calloc(40, sizeof(SolAccountMeta));
|
||||
sol_log_64(0, 0, 0, 0, (uint64_t)arguments);
|
||||
sol_assert(0 != arguments);
|
||||
uint8_t data[] = {};
|
||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
arguments, 40, data,
|
||||
SOL_ARRAY_SIZE(data)};
|
||||
const SolSignerSeeds signers_seeds[] = {};
|
||||
sol_assert(SUCCESS == sol_invoke_signed(
|
||||
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
|
||||
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sol_panic();
|
||||
}
|
||||
|
@@ -24,6 +24,8 @@ const TEST_EMPTY_ACCOUNTS_SLICE: u8 = 5;
|
||||
const TEST_CAP_SEEDS: u8 = 6;
|
||||
const TEST_CAP_SIGNERS: u8 = 7;
|
||||
const TEST_ALLOC_ACCESS_VIOLATION: u8 = 8;
|
||||
const TEST_INSTRUCTION_DATA_TOO_LARGE: u8 = 9;
|
||||
const TEST_INSTRUCTION_META_TOO_LARGE: u8 = 10;
|
||||
|
||||
// const MINT_INDEX: usize = 0;
|
||||
const ARGUMENT_INDEX: usize = 1;
|
||||
@@ -497,6 +499,21 @@ fn process_instruction(
|
||||
&[&[b"You pass butter", &[bump_seed1]]],
|
||||
)?;
|
||||
}
|
||||
TEST_INSTRUCTION_DATA_TOO_LARGE => {
|
||||
msg!("Test instruction data too large");
|
||||
let instruction =
|
||||
create_instruction(*accounts[INVOKED_PROGRAM_INDEX].key, &[], vec![0; 1500]);
|
||||
invoke_signed(&instruction, &[], &[])?;
|
||||
}
|
||||
TEST_INSTRUCTION_META_TOO_LARGE => {
|
||||
msg!("Test instruction metas too large");
|
||||
let instruction = create_instruction(
|
||||
*accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
&[(&Pubkey::default(), false, false); 40],
|
||||
vec![],
|
||||
);
|
||||
invoke_signed(&instruction, &[], &[])?;
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
||||
|
@@ -566,6 +566,8 @@ fn test_program_bpf_invoke() {
|
||||
const TEST_CAP_SEEDS: u8 = 6;
|
||||
const TEST_CAP_SIGNERS: u8 = 7;
|
||||
const TEST_ALLOC_ACCESS_VIOLATION: u8 = 8;
|
||||
const TEST_INSTRUCTION_DATA_TOO_LARGE: u8 = 9;
|
||||
const TEST_INSTRUCTION_META_TOO_LARGE: u8 = 10;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
@@ -894,6 +896,70 @@ fn test_program_bpf_invoke() {
|
||||
TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
|
||||
);
|
||||
|
||||
let instruction = Instruction::new(
|
||||
invoke_program_id,
|
||||
&[
|
||||
TEST_INSTRUCTION_DATA_TOO_LARGE,
|
||||
bump_seed1,
|
||||
bump_seed2,
|
||||
bump_seed3,
|
||||
],
|
||||
account_metas.clone(),
|
||||
);
|
||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||
let tx = Transaction::new(
|
||||
&[
|
||||
&mint_keypair,
|
||||
&argument_keypair,
|
||||
&invoked_argument_keypair,
|
||||
&from_keypair,
|
||||
],
|
||||
message.clone(),
|
||||
bank.last_blockhash(),
|
||||
);
|
||||
let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
|
||||
let invoked_programs: Vec<Pubkey> = inner_instructions[0]
|
||||
.iter()
|
||||
.map(|ix| message.account_keys[ix.program_id_index as usize].clone())
|
||||
.collect();
|
||||
assert_eq!(invoked_programs, vec![]);
|
||||
assert_eq!(
|
||||
result.unwrap_err(),
|
||||
TransactionError::InstructionError(0, InstructionError::ComputationalBudgetExceeded)
|
||||
);
|
||||
|
||||
let instruction = Instruction::new(
|
||||
invoke_program_id,
|
||||
&[
|
||||
TEST_INSTRUCTION_META_TOO_LARGE,
|
||||
bump_seed1,
|
||||
bump_seed2,
|
||||
bump_seed3,
|
||||
],
|
||||
account_metas.clone(),
|
||||
);
|
||||
let message = Message::new(&[instruction], Some(&mint_pubkey));
|
||||
let tx = Transaction::new(
|
||||
&[
|
||||
&mint_keypair,
|
||||
&argument_keypair,
|
||||
&invoked_argument_keypair,
|
||||
&from_keypair,
|
||||
],
|
||||
message.clone(),
|
||||
bank.last_blockhash(),
|
||||
);
|
||||
let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
|
||||
let invoked_programs: Vec<Pubkey> = inner_instructions[0]
|
||||
.iter()
|
||||
.map(|ix| message.account_keys[ix.program_id_index as usize].clone())
|
||||
.collect();
|
||||
assert_eq!(invoked_programs, vec![]);
|
||||
assert_eq!(
|
||||
result.unwrap_err(),
|
||||
TransactionError::InstructionError(0, InstructionError::ComputationalBudgetExceeded)
|
||||
);
|
||||
|
||||
// Check final state
|
||||
|
||||
assert_eq!(43, bank.get_balance(&derived_key1));
|
||||
|
Reference in New Issue
Block a user