Skip to content

Commit

Permalink
vote_state_deserialize: add missing safety docs
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrod committed Jul 29, 2024
1 parent 5e0a733 commit d78c70b
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 0 deletions.
5 changes: 5 additions & 0 deletions sdk/program/src/vote/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,11 @@ impl VoteState {
0 => {
#[cfg(not(target_os = "solana"))]
{
// Safety: vote_state is valid as it comes from `&mut MaybeUninit<VoteState>` or
// `&mut VoteState`. In the first case, the value is uninitialized so we write()
// to avoid dropping invalid data; in the latter case, we `drop_in_place()`
// before writing so the value has already been dropped and we just write a new
// one in place.
unsafe {
vote_state.write(
bincode::deserialize::<VoteStateVersions>(input)
Expand Down
6 changes: 6 additions & 0 deletions sdk/program/src/vote/state/vote_state_deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ pub(super) fn deserialize_vote_state_into(
vote_state: *mut VoteState,
has_latency: bool,
) -> Result<(), InstructionError> {
// Safety: if vote_state is non-null, all the fields are guaranteed to be valid pointers
unsafe {
addr_of_mut!((*vote_state).node_pubkey).write(read_pubkey(cursor)?);
addr_of_mut!((*vote_state).authorized_withdrawer).write(read_pubkey(cursor)?);
addr_of_mut!((*vote_state).commission).write(read_u8(cursor)?);
}

let votes = read_votes(cursor, has_latency)?;
// Safety: if vote_state is non-null, root_slot is guaranteed to be valid too
unsafe {
addr_of_mut!((*vote_state).root_slot).write(read_option_u64(cursor)?);
}
Expand All @@ -33,6 +36,8 @@ pub(super) fn deserialize_vote_state_into(

// Defer writing the collections until we know we're going to succeed. This way if we fail we
// still drop the collections and don't leak memory.
//
// Safety: if vote_state is non-null, all the fields are guaranteed to be valid pointers
unsafe {
addr_of_mut!((*vote_state).votes).write(votes);
addr_of_mut!((*vote_state).authorized_voters).write(authorized_voters);
Expand Down Expand Up @@ -81,6 +86,7 @@ fn read_prior_voters_into<T: AsRef<[u8]>>(
cursor: &mut Cursor<T>,
vote_state: *mut VoteState,
) -> Result<(), InstructionError> {
// Safety: if vote_state is non-null, prior_voters is guaranteed to be valid too
unsafe {
let prior_voters = addr_of_mut!((*vote_state).prior_voters);
let prior_voters_buf = addr_of_mut!((*prior_voters).buf) as *mut (Pubkey, u64, u64);
Expand Down

0 comments on commit d78c70b

Please sign in to comment.