Skip to content

Commit da6459d

Browse files
chore: remove unwraps system program (#1803)
* chore: remove unwraps system program * fix: add out of bounds check for concurrent Merkle tree deserialization * Update anchor-programs/system/src/errors.rs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent d22e1eb commit da6459d

File tree

8 files changed

+137
-68
lines changed

8 files changed

+137
-68
lines changed

anchor-programs/system/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,6 @@ pub enum SystemProgramError {
8686
CpiContextAlreadySet,
8787
InvalidTreeHeight,
8888
TooManyOutputAccounts,
89+
#[msg("Failed to borrow account data")]
90+
BorrowingDataFailed,
8991
}

js/compressed-token/src/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ export type BatchCompressInstructionData = {
7373
bump: number;
7474
};
7575

76-
7776
export type MintToInstructionData = {
7877
recipients: PublicKey[];
7978
amounts: BN[];

programs/system/src/account_compression_state/address.rs

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,23 @@ pub struct AddressMerkleTreeAccount {
2020
pub fn address_merkle_tree_from_bytes_zero_copy(
2121
data: &[u8],
2222
) -> Result<IndexedMerkleTreeZeroCopy<Poseidon, usize, 26, 16>> {
23-
let data = &data[8 + mem::size_of::<AddressMerkleTreeAccount>()..];
24-
let merkle_tree = IndexedMerkleTreeZeroCopy::from_bytes_zero_copy(data).unwrap();
25-
Ok(merkle_tree)
26-
}
27-
28-
pub fn address_merkle_tree_from_bytes_zero_copy_init(
29-
data: &mut [u8],
30-
height: usize,
31-
canopy_depth: usize,
32-
changelog_capacity: usize,
33-
roots_capacity: usize,
34-
indexed_changelog_capacity: usize,
35-
) -> Result<IndexedMerkleTreeZeroCopyMut<Poseidon, usize, 26, 16>> {
36-
let data = &mut data[8 + mem::size_of::<AddressMerkleTreeAccount>()..];
37-
let merkle_tree = IndexedMerkleTreeZeroCopyMut::from_bytes_zero_copy_init(
38-
data,
39-
height,
40-
canopy_depth,
41-
changelog_capacity,
42-
roots_capacity,
43-
indexed_changelog_capacity,
44-
)
45-
.unwrap();
23+
let required_size = 8 + mem::size_of::<AddressMerkleTreeAccount>();
24+
if data.len() < required_size {
25+
return Err(crate::errors::SystemProgramError::InvalidAccount.into());
26+
}
27+
let data = &data[required_size..];
28+
let merkle_tree = IndexedMerkleTreeZeroCopy::from_bytes_zero_copy(data)?;
4629
Ok(merkle_tree)
4730
}
4831

4932
pub fn address_merkle_tree_from_bytes_zero_copy_mut(
5033
data: &mut [u8],
5134
) -> Result<IndexedMerkleTreeZeroCopyMut<Poseidon, usize, 26, 16>> {
52-
let data = &mut data[8 + mem::size_of::<AddressMerkleTreeAccount>()..];
53-
let merkle_tree = IndexedMerkleTreeZeroCopyMut::from_bytes_zero_copy_mut(data).unwrap();
35+
let required_size = 8 + mem::size_of::<AddressMerkleTreeAccount>();
36+
if data.len() < required_size {
37+
return Err(crate::errors::SystemProgramError::InvalidAccount.into());
38+
}
39+
let data = &mut data[required_size..];
40+
let merkle_tree = IndexedMerkleTreeZeroCopyMut::from_bytes_zero_copy_mut(data)?;
5441
Ok(merkle_tree)
5542
}

programs/system/src/account_compression_state/state.rs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,37 +49,26 @@ impl StateMerkleTreeAccount {
4949
}
5050
}
5151

52-
pub fn state_merkle_tree_from_bytes_zero_copy_init(
53-
data: &mut [u8],
54-
height: usize,
55-
canopy_depth: usize,
56-
changelog_capacity: usize,
57-
roots_capacity: usize,
58-
) -> Result<ConcurrentMerkleTreeZeroCopyMut<Poseidon, 26>> {
59-
let data = &mut data[8 + mem::size_of::<StateMerkleTreeAccount>()..];
60-
let merkle_tree = ConcurrentMerkleTreeZeroCopyMut::from_bytes_zero_copy_init(
61-
data,
62-
height,
63-
canopy_depth,
64-
changelog_capacity,
65-
roots_capacity,
66-
)
67-
.unwrap();
68-
Ok(merkle_tree)
69-
}
70-
7152
pub fn state_merkle_tree_from_bytes_zero_copy(
7253
data: &[u8],
7354
) -> Result<ConcurrentMerkleTreeZeroCopy<Poseidon, 26>> {
74-
let data = &data[8 + mem::size_of::<StateMerkleTreeAccount>()..];
75-
let merkle_tree = ConcurrentMerkleTreeZeroCopy::from_bytes_zero_copy(data).unwrap();
55+
let required_size = 8 + mem::size_of::<StateMerkleTreeAccount>();
56+
if data.len() < required_size {
57+
return Err(crate::errors::SystemProgramError::InvalidAccount.into());
58+
}
59+
let data = &data[required_size..];
60+
let merkle_tree = ConcurrentMerkleTreeZeroCopy::from_bytes_zero_copy(data)?;
7661
Ok(merkle_tree)
7762
}
7863

7964
pub fn state_merkle_tree_from_bytes_zero_copy_mut(
8065
data: &mut [u8],
8166
) -> Result<ConcurrentMerkleTreeZeroCopyMut<Poseidon, 26>> {
82-
let data = &mut data[8 + mem::size_of::<StateMerkleTreeAccount>()..];
83-
let merkle_tree = ConcurrentMerkleTreeZeroCopyMut::from_bytes_zero_copy_mut(data).unwrap();
67+
let required_size = 8 + mem::size_of::<StateMerkleTreeAccount>();
68+
if data.len() < required_size {
69+
return Err(crate::errors::SystemProgramError::InvalidAccount.into());
70+
}
71+
let data = &mut data[required_size..];
72+
let merkle_tree = ConcurrentMerkleTreeZeroCopyMut::from_bytes_zero_copy_mut(data)?;
8473
Ok(merkle_tree)
8574
}

programs/system/src/accounts/remaining_account_checks.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub(crate) fn try_from_account_info<'a, 'info: 'a>(
6868
{
6969
let data = account_info
7070
.try_borrow_data()
71-
.map_err(|_| SystemProgramError::InvalidAccount)?;
71+
.map_err(|_| SystemProgramError::BorrowingDataFailed)?;
7272

7373
if data.len() < 8 {
7474
return Ok(AcpAccount::Unknown());
@@ -82,20 +82,18 @@ pub(crate) fn try_from_account_info<'a, 'info: 'a>(
8282
tree_type.copy_from_slice(
8383
&account_info
8484
.try_borrow_data()
85-
.map_err(|_| SystemProgramError::InvalidAccount)?[8..16],
85+
.map_err(|_| SystemProgramError::BorrowingDataFailed)?[8..16],
8686
);
8787
let tree_type = TreeType::from(u64::from_le_bytes(tree_type));
8888
match tree_type {
8989
TreeType::AddressV2 => {
90-
let tree =
91-
BatchedMerkleTreeAccount::address_from_account_info(account_info).unwrap();
90+
let tree = BatchedMerkleTreeAccount::address_from_account_info(account_info)?;
9291
let program_owner = tree.metadata.access_metadata.program_owner;
9392
// for batched trees we set the fee when setting the rollover fee.
9493
Ok((AcpAccount::BatchedAddressTree(tree), program_owner))
9594
}
9695
TreeType::StateV2 => {
97-
let tree =
98-
BatchedMerkleTreeAccount::state_from_account_info(account_info).unwrap();
96+
let tree = BatchedMerkleTreeAccount::state_from_account_info(account_info)?;
9997
let program_owner = tree.metadata.access_metadata.program_owner;
10098
Ok((AcpAccount::BatchedStateTree(tree), program_owner))
10199
}
@@ -111,14 +109,16 @@ pub(crate) fn try_from_account_info<'a, 'info: 'a>(
111109
}
112110
}
113111
BatchedQueueAccount::LIGHT_DISCRIMINATOR => {
114-
let queue = BatchedQueueAccount::output_from_account_info(account_info).unwrap();
112+
let queue = BatchedQueueAccount::output_from_account_info(account_info)?;
115113
let program_owner = queue.metadata.access_metadata.program_owner;
116114
Ok((AcpAccount::OutputQueue(queue), program_owner))
117115
}
118116
STATE_MERKLE_TREE_ACCOUNT_DISCRIMINATOR => {
119117
let program_owner = {
120-
check_owner(&ACCOUNT_COMPRESSION_PROGRAM_ID, account_info).unwrap();
121-
let data = account_info.try_borrow_data().unwrap();
118+
check_owner(&ACCOUNT_COMPRESSION_PROGRAM_ID, account_info)?;
119+
let data = account_info
120+
.try_borrow_data()
121+
.map_err(|_| SystemProgramError::BorrowingDataFailed)?;
122122
let merkle_tree = bytemuck::from_bytes::<StateMerkleTreeAccount>(
123123
&data[8..StateMerkleTreeAccount::LEN],
124124
);
@@ -144,15 +144,18 @@ pub(crate) fn try_from_account_info<'a, 'info: 'a>(
144144
Ok((
145145
AcpAccount::StateTree((
146146
(*account_info.key()).into(),
147-
state_merkle_tree_from_bytes_zero_copy_mut(data_slice).unwrap(),
147+
state_merkle_tree_from_bytes_zero_copy_mut(data_slice)
148+
.map_err(|e| SystemProgramError::ProgramError(e.into()))?,
148149
)),
149150
program_owner,
150151
))
151152
}
152153
ADDRESS_MERKLE_TREE_ACCOUNT_DISCRIMINATOR => {
153154
let program_owner = {
154-
check_owner(&ACCOUNT_COMPRESSION_PROGRAM_ID, account_info).unwrap();
155-
let data = account_info.try_borrow_data().unwrap();
155+
check_owner(&ACCOUNT_COMPRESSION_PROGRAM_ID, account_info)?;
156+
let data = account_info
157+
.try_borrow_data()
158+
.map_err(|_| SystemProgramError::BorrowingDataFailed)?;
156159

157160
let merkle_tree = bytemuck::from_bytes::<AddressMerkleTreeAccount>(
158161
&data[8..AddressMerkleTreeAccount::LEN],
@@ -170,14 +173,17 @@ pub(crate) fn try_from_account_info<'a, 'info: 'a>(
170173
Ok((
171174
AcpAccount::AddressTree((
172175
(*account_info.key()).into(),
173-
address_merkle_tree_from_bytes_zero_copy_mut(data_slice).unwrap(),
176+
address_merkle_tree_from_bytes_zero_copy_mut(data_slice)
177+
.map_err(|e| SystemProgramError::ProgramError(e.into()))?,
174178
)),
175179
program_owner,
176180
))
177181
}
178182
QUEUE_ACCOUNT_DISCRIMINATOR => {
179-
check_owner(&ACCOUNT_COMPRESSION_PROGRAM_ID, account_info).unwrap();
180-
let data = account_info.try_borrow_data().unwrap();
183+
check_owner(&ACCOUNT_COMPRESSION_PROGRAM_ID, account_info)?;
184+
let data = account_info
185+
.try_borrow_data()
186+
.map_err(|_| SystemProgramError::BorrowingDataFailed)?;
181187
let queue = bytemuck::from_bytes::<QueueAccount>(&data[8..QueueAccount::LEN]);
182188

183189
if queue.metadata.queue_type == QueueType::AddressV1 as u64 {

programs/system/src/errors.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
use light_account_checks::error::AccountError;
2+
use light_batched_merkle_tree::errors::BatchedMerkleTreeError;
3+
use light_concurrent_merkle_tree::errors::ConcurrentMerkleTreeError;
4+
use light_indexed_merkle_tree::errors::IndexedMerkleTreeError;
5+
use light_zero_copy::errors::ZeroCopyError;
16
use pinocchio::program_error::ProgramError;
27
use thiserror::Error;
38

@@ -107,10 +112,90 @@ pub enum SystemProgramError {
107112
InvalidTreeHeight,
108113
#[error("TooManyOutputAccounts")]
109114
TooManyOutputAccounts,
115+
#[error("Batched Merkle tree error {0}")]
116+
BatchedMerkleTreeError(#[from] BatchedMerkleTreeError),
117+
#[error("Concurrent Merkle tree error {0}")]
118+
ConcurrentMerkleTreeError(#[from] ConcurrentMerkleTreeError),
119+
#[error("Indexed Merkle tree error {0}")]
120+
IndexedMerkleTreeError(#[from] IndexedMerkleTreeError),
121+
#[error("Account checks error {0}")]
122+
AccountError(#[from] AccountError),
123+
#[error("Zero copy error {0}")]
124+
ZeroCopyError(#[from] ZeroCopyError),
125+
#[error("Program error code: {0}")]
126+
ProgramError(u64),
127+
#[error("Borrowing data failed")]
128+
BorrowingDataFailed,
129+
}
130+
131+
impl From<SystemProgramError> for u32 {
132+
fn from(e: SystemProgramError) -> u32 {
133+
match e {
134+
SystemProgramError::SumCheckFailed => 6000,
135+
SystemProgramError::SignerCheckFailed => 6001,
136+
SystemProgramError::CpiSignerCheckFailed => 6002,
137+
SystemProgramError::ComputeInputSumFailed => 6003,
138+
SystemProgramError::ComputeOutputSumFailed => 6004,
139+
SystemProgramError::ComputeRpcSumFailed => 6005,
140+
SystemProgramError::InvalidAddress => 6006,
141+
SystemProgramError::DeriveAddressError => 6007,
142+
SystemProgramError::CompressedSolPdaUndefinedForCompressSol => 6008,
143+
SystemProgramError::DecompressLamportsUndefinedForCompressSol => 6009,
144+
SystemProgramError::CompressedSolPdaUndefinedForDecompressSol => 6010,
145+
SystemProgramError::DeCompressLamportsUndefinedForDecompressSol => 6011,
146+
SystemProgramError::DecompressRecipientUndefinedForDecompressSol => 6012,
147+
SystemProgramError::WriteAccessCheckFailed => 6013,
148+
SystemProgramError::InvokingProgramNotProvided => 6014,
149+
SystemProgramError::InvalidCapacity => 6015,
150+
SystemProgramError::InvalidMerkleTreeOwner => 6016,
151+
SystemProgramError::ProofIsNone => 6017,
152+
SystemProgramError::ProofIsSome => 6018,
153+
SystemProgramError::EmptyInputs => 6019,
154+
SystemProgramError::CpiContextAccountUndefined => 6020,
155+
SystemProgramError::CpiContextEmpty => 6021,
156+
SystemProgramError::CpiContextMissing => 6022,
157+
SystemProgramError::DecompressionRecipientDefined => 6023,
158+
SystemProgramError::SolPoolPdaDefined => 6024,
159+
SystemProgramError::AppendStateFailed => 6025,
160+
SystemProgramError::InstructionNotCallable => 6026,
161+
SystemProgramError::CpiContextFeePayerMismatch => 6027,
162+
SystemProgramError::CpiContextAssociatedMerkleTreeMismatch => 6028,
163+
SystemProgramError::NoInputs => 6029,
164+
SystemProgramError::InputMerkleTreeIndicesNotInOrder => 6030,
165+
SystemProgramError::OutputMerkleTreeIndicesNotInOrder => 6031,
166+
SystemProgramError::OutputMerkleTreeNotUnique => 6032,
167+
SystemProgramError::DataFieldUndefined => 6033,
168+
SystemProgramError::ReadOnlyAddressAlreadyExists => 6034,
169+
SystemProgramError::ReadOnlyAccountDoesNotExist => 6035,
170+
SystemProgramError::HashChainInputsLenghtInconsistent => 6036,
171+
SystemProgramError::InvalidAddressTreeHeight => 6037,
172+
SystemProgramError::InvalidStateTreeHeight => 6038,
173+
SystemProgramError::InvalidArgument => 6039,
174+
SystemProgramError::InvalidAccount => 6040,
175+
SystemProgramError::AddressMerkleTreeAccountDiscriminatorMismatch => 6041,
176+
SystemProgramError::StateMerkleTreeAccountDiscriminatorMismatch => 6042,
177+
SystemProgramError::ProofVerificationFailed => 6043,
178+
SystemProgramError::InvalidAccountMode => 6044,
179+
SystemProgramError::InvalidInstructionDataDiscriminator => 6045,
180+
SystemProgramError::NewAddressAssignedIndexOutOfBounds => 6046,
181+
SystemProgramError::AddressIsNone => 6047,
182+
SystemProgramError::AddressDoesNotMatch => 6048,
183+
SystemProgramError::CpiContextAlreadySet => 6049,
184+
SystemProgramError::InvalidTreeHeight => 6050,
185+
SystemProgramError::TooManyOutputAccounts => 6051,
186+
SystemProgramError::BatchedMerkleTreeError(e) => e.into(),
187+
SystemProgramError::IndexedMerkleTreeError(e) => e.into(),
188+
SystemProgramError::ConcurrentMerkleTreeError(e) => e.into(),
189+
SystemProgramError::AccountError(e) => e.into(),
190+
SystemProgramError::ProgramError(e) => u32::try_from(e).unwrap_or(0),
191+
SystemProgramError::BorrowingDataFailed => 6052,
192+
SystemProgramError::ZeroCopyError(e) => e.into(),
193+
}
194+
}
110195
}
111196

112197
impl From<SystemProgramError> for ProgramError {
113198
fn from(e: SystemProgramError) -> ProgramError {
114-
ProgramError::Custom(e as u32 + 6000)
199+
ProgramError::Custom(e.into())
115200
}
116201
}

programs/system/src/invoke_cpi/process_cpi_context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ pub fn set_cpi_context<'a, 'info, T: InstructionData<'a>>(
105105
use borsh::{BorshDeserialize, BorshSerialize};
106106
let cpi_context_account = {
107107
let data = cpi_context_account_info.try_borrow_data()?;
108-
let mut cpi_context_account = CpiContextAccount::deserialize(&mut &data[8..]).unwrap();
108+
let mut cpi_context_account = CpiContextAccount::deserialize(&mut &data[8..])
109+
.map_err(|_| SystemProgramError::BorrowingDataFailed)?;
109110
if instruction_data.cpi_context().unwrap().first_set_context {
110111
cpi_context_account.context.clear();
111112
cpi_context_account.fee_payer = fee_payer;

programs/system/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub fn invoke<'a, 'b, 'c: 'info, 'info>(
9191
// remove vec prefix
9292
let instruction_data = &instruction_data[4..];
9393

94-
let (inputs, _) = ZInstructionDataInvoke::zero_copy_at(instruction_data).unwrap();
94+
let (inputs, _) = ZInstructionDataInvoke::zero_copy_at(instruction_data)?;
9595
let (ctx, remaining_accounts) = InvokeInstruction::from_account_infos(accounts)?;
9696

9797
input_compressed_accounts_signer_check(
@@ -117,7 +117,7 @@ pub fn invoke_cpi<'a, 'b, 'c: 'info, 'info>(
117117
// remove vec prefix
118118
let instruction_data = &instruction_data[4..];
119119

120-
let (inputs, _) = ZInstructionDataInvokeCpi::zero_copy_at(instruction_data).unwrap();
120+
let (inputs, _) = ZInstructionDataInvokeCpi::zero_copy_at(instruction_data)?;
121121

122122
let (ctx, remaining_accounts) = InvokeCpiInstruction::from_account_infos(accounts)?;
123123

0 commit comments

Comments
 (0)