Skip to content

Commit 917c43b

Browse files
authored
fix: prevent out-of-bounds write in derive_address (#2088)
The bounds check allowed seeds.len() == MAX_SEEDS, but the data array is [MAX_SEEDS + 2] and needs to hold seeds + bump + program_id + PDA_MARKER (3 extra items). This caused an OOB write at index MAX_SEEDS + 2 when seeds.len() == MAX_SEEDS. Changed check from > to >= MAX_SEEDS in both check_seeds() and derive_address().
1 parent 8328855 commit 917c43b

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

program-libs/ctoken-types/src/instructions/extensions/compressible.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ pub struct CompressToPubkey {
3535

3636
impl CompressToPubkey {
3737
pub fn check_seeds(&self, pubkey: &Pubkey) -> Result<(), CTokenError> {
38-
if self.seeds.len() > MAX_SEEDS {
39-
return Err(CTokenError::TooManySeeds(MAX_SEEDS));
38+
if self.seeds.len() >= MAX_SEEDS {
39+
return Err(CTokenError::TooManySeeds(MAX_SEEDS - 1));
4040
}
4141
let mut references = ArrayVec::<[&[u8]; MAX_SEEDS]>::new();
4242
for seed in self.seeds.iter() {
@@ -61,8 +61,10 @@ pub fn derive_address(
6161
program_id: &Pubkey,
6262
) -> Result<Pubkey, CTokenError> {
6363
const PDA_MARKER: &[u8; 21] = b"ProgramDerivedAddress";
64-
if seeds.len() > MAX_SEEDS {
65-
return Err(CTokenError::TooManySeeds(MAX_SEEDS));
64+
// Must be strictly less than MAX_SEEDS because we need space for:
65+
// seeds + bump + program_id + PDA_MARKER in a [MAX_SEEDS + 2] array
66+
if seeds.len() >= MAX_SEEDS {
67+
return Err(CTokenError::TooManySeeds(MAX_SEEDS - 1));
6668
}
6769
const UNINIT: MaybeUninit<&[u8]> = MaybeUninit::<&[u8]>::uninit();
6870
let mut data = [UNINIT; MAX_SEEDS + 2];

0 commit comments

Comments
 (0)