diff --git a/program/src/processor/initialize.rs b/program/src/processor/initialize.rs index 4c39ed4..89a7f24 100644 --- a/program/src/processor/initialize.rs +++ b/program/src/processor/initialize.rs @@ -1,3 +1,5 @@ +use core::mem::{align_of, size_of}; + use pinocchio::{ cpi::{Seed, Signer}, error::ProgramError, @@ -215,8 +217,13 @@ struct Initialize { pub data_source: u8, } +// Enforces 1-byte alignment for the struct. +const _: () = { + assert!(align_of::() == 1); +}; + impl Initialize { - const LEN: usize = core::mem::size_of::(); + const LEN: usize = size_of::(); /// # Safety /// diff --git a/program/src/processor/set_data.rs b/program/src/processor/set_data.rs index 8cae122..44a0d11 100644 --- a/program/src/processor/set_data.rs +++ b/program/src/processor/set_data.rs @@ -1,3 +1,5 @@ +use core::mem::{align_of, size_of}; + use pinocchio::{account::AccountView, error::ProgramError, ProgramResult, Resize}; use crate::state::{ @@ -164,8 +166,13 @@ struct SetData { // - `&[u8]`: remaining data } +// Enforces 1-byte alignment for the struct. +const _: () = { + assert!(align_of::() == 1); +}; + impl SetData { - const LEN: usize = core::mem::size_of::(); + const LEN: usize = size_of::(); /// # Safety /// diff --git a/program/src/processor/write.rs b/program/src/processor/write.rs index 11384a6..60efd3a 100644 --- a/program/src/processor/write.rs +++ b/program/src/processor/write.rs @@ -122,7 +122,6 @@ pub fn write(accounts: &mut [AccountView], instruction_data: &[u8]) -> ProgramRe } /// Instruction data expected by the `Write` instruction. -#[repr(C)] struct Write<'a> { /// Offset to write to. offset: &'a [u8; 4], diff --git a/program/src/state/buffer.rs b/program/src/state/buffer.rs index 19da923..e7fec28 100644 --- a/program/src/state/buffer.rs +++ b/program/src/state/buffer.rs @@ -1,3 +1,5 @@ +use core::mem::align_of; + use pinocchio::{ account::{AccountView, Ref}, error::ProgramError, @@ -41,6 +43,11 @@ pub struct Buffer { _padding: [u8; 14], } +// Enforces 1-byte alignment for the struct. +const _: () = { + assert!(align_of::() == 1); +}; + impl Buffer { /// The minimum size of a `Buffer` (`96` bytes). pub const LEN: usize = core::mem::size_of::(); diff --git a/program/src/state/data.rs b/program/src/state/data.rs index b2918ed..60ed53b 100644 --- a/program/src/state/data.rs +++ b/program/src/state/data.rs @@ -1,3 +1,5 @@ +use core::{mem::align_of, str::from_utf8}; + use pinocchio::{error::ProgramError, Address}; use super::{DataSource, ZeroableOption}; @@ -23,12 +25,15 @@ impl<'a> Data<'a> { Ok(match data_source { DataSource::Direct => Data::Direct(DirectData(bytes)), DataSource::Url => Data::Url(UrlData( - core::str::from_utf8(bytes).map_err(|_| ProgramError::InvalidArgument)?, + from_utf8(bytes).map_err(|_| ProgramError::InvalidArgument)?, )), DataSource::External => { if bytes.len() < ExternalData::LEN { return Err(ProgramError::InvalidArgument); } + if !(bytes.as_ptr() as usize).is_multiple_of(align_of::()) { + return Err(ProgramError::InvalidArgument); + } // SAFETY: `bytes` was validated to have the expected length // to hold a `Data::External` reference. Data::External(unsafe { &*(bytes.as_ptr() as *const ExternalData) }) @@ -67,6 +72,11 @@ pub struct ExternalData { pub length: ZeroableOption, } +// Enforces 4-byte alignment for the `ExternalData` struct. +const _: () = { + assert!(align_of::() == 4); +}; + impl ExternalData { pub const LEN: usize = core::mem::size_of::(); } diff --git a/program/src/state/header.rs b/program/src/state/header.rs index 4613b9e..faed548 100644 --- a/program/src/state/header.rs +++ b/program/src/state/header.rs @@ -1,3 +1,5 @@ +use core::mem::align_of; + use pinocchio::{ account::{AccountView, Ref}, error::ProgramError, @@ -56,6 +58,11 @@ pub struct Header { _padding: [u8; 5], } +// Enforces 1-byte alignment for the struct. +const _: () = { + assert!(align_of::
() == 1); +}; + impl Header { /// Length of the header (96 bytes). pub const LEN: usize = core::mem::size_of::
(); diff --git a/program/src/state/mod.rs b/program/src/state/mod.rs index 16010fb..fd988c4 100644 --- a/program/src/state/mod.rs +++ b/program/src/state/mod.rs @@ -2,12 +2,26 @@ pub mod buffer; pub mod data; pub mod header; -use pinocchio::{address::ADDRESS_BYTES, error::ProgramError, Address, ProgramResult}; +use core::mem::size_of; -use data::{Data, ExternalData}; -use header::Header; +use pinocchio::{address::ADDRESS_BYTES, error::ProgramError, Address, ProgramResult}; -use crate::error::ProgramMetadataError; +use crate::{ + error::ProgramMetadataError, + state::{ + buffer::Buffer, + data::{Data, ExternalData}, + header::Header, + }, +}; + +// Make sure both `Header` and `Buffer` structs have the same size. +const _: () = { + assert!( + size_of::
() == size_of::(), + "Header and Buffer should be the same size" + ); +}; /// The length of the seed used to derive the metadata account address. pub const SEED_LEN: usize = 16;