Skip to content

Commit

Permalink
If the account length is zero, no data region is present (#5122)
Browse files Browse the repository at this point in the history
This only affects unaligned programs, as for aligned programs the resize
area address will match the account region address if the data length is
zero.

(cherry picked from commit 561023d)
  • Loading branch information
seanyoung committed Mar 5, 2025
1 parent f8de613 commit a9f3a91
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 5 deletions.
4 changes: 2 additions & 2 deletions programs/bpf_loader/src/syscalls/mem_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ impl<'a> Iterator for MemoryChunkIterator<'a> {
account_index = account_index.saturating_add(1);
self.account_index = Some(account_index);
} else {
region_is_account = region.vm_addr == account_addr
region_is_account = (account.original_data_len != 0 && region.vm_addr == account_addr)
// unaligned programs do not have a resize area
|| (self.resize_area && region.vm_addr == resize_addr);
break;
Expand Down Expand Up @@ -606,7 +606,7 @@ impl DoubleEndedIterator for MemoryChunkIterator<'_> {

self.account_index = Some(account_index);
} else {
region_is_account = region.vm_addr == account_addr
region_is_account = (account.original_data_len != 0 && region.vm_addr == account_addr)
// unaligned programs do not have a resize area
|| (self.resize_area && region.vm_addr == resize_addr);
break;
Expand Down
7 changes: 7 additions & 0 deletions programs/sbf/rust/account_mem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,15 @@ pub fn process_instruction(
sol_memset(&mut data[data_len.saturating_sub(2)..], 0, 3);
}
5 => {
// memcmp overlaps begining
#[allow(clippy::manual_memcpy)]
for i in 0..3 {
buf[i] = too_early(2)[i];
}

// memset overlaps begin of account area
sol_memset(too_early(2), 3, 3);
sol_memcpy(too_early(2), &buf, 3);
}
6 => {
// memcpy src overlaps end of account
Expand Down
6 changes: 3 additions & 3 deletions programs/sbf/rust/account_mem_deprecated/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn process_instruction(
let mut too_early = |before: usize| -> &mut [u8] {
let data = data.as_mut_ptr().wrapping_sub(before);

unsafe { std::slice::from_raw_parts_mut(data, data_len) }
unsafe { std::slice::from_raw_parts_mut(data, data_len.wrapping_add(100)) }
};

match instruction_data[0] {
Expand All @@ -40,11 +40,11 @@ pub fn process_instruction(
2 => {
// memcmp overlaps begining
#[allow(clippy::manual_memcpy)]
for i in 0..500 {
for i in 0..90 {
buf[i] = too_early(8)[i];
}

sol_memcmp(too_early(8), &buf, 500);
sol_memcmp(too_early(8), &buf, 90);
}
3 => {
// memcmp overlaps begining
Expand Down
23 changes: 23 additions & 0 deletions programs/sbf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5194,6 +5194,29 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
assert!(!logs.last().unwrap().ends_with(" failed: InvalidLength"));
}
}

let account = AccountSharedData::new(42, 0, &program_id);
bank.store_account(&account_keypair.pubkey(), &account);

for instr in 0..=15 {
println!("Testing deprecated:{deprecated} direct_mapping:{direct_mapping} instruction:{instr} zero-length account");
let instruction =
Instruction::new_with_bytes(program_id, &[instr, 0], 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);

if direct_mapping && !deprecated {
// we have a resize area
assert!(
logs.last().unwrap().ends_with(" failed: InvalidLength"),
"{logs:?}"
);
} else {
assert!(result.is_ok(), "{logs:?}");
}
}
}
}
}

0 comments on commit a9f3a91

Please sign in to comment.