Assessment reports>Pinocchio and p-token>Discussion>New off-chain implementation of impl_sysvar_get may return different ProgramError

New off-chain implementation of impl_sysvar_get may return different ProgramError

The previous implementation of getting various system variables did not differentiate between on chain and off chain and would always return the constant UNSUPPORTED_SYSVAR if the sysvar was unsupported.

In the new implementation, there is a difference in the on-chain and off-chain code, where the off-chain portion may return a value that does not match UNSUPPORTED_SYSVAR.

macro_rules! impl_sysvar_get {
    ($syscall_name:ident) => {
        fn get() -> Result<Self, $crate::program_error::ProgramError> {
            let mut var = core::mem::MaybeUninit::<Self>::uninit();
            let var_addr = var.as_mut_ptr() as *mut _ as *mut u8;

            #[cfg(target_os = "solana")]
            let result = unsafe { $crate::syscalls::$syscall_name(var_addr) };

!            #[cfg(not(target_os = "solana"))]
!            let result = core::hint::black_box(var_addr as *const _ as u64);

            match result {
                // SAFETY: The syscall initialized the memory.
                $crate::SUCCESS => Ok(unsafe { var.assume_init() }),
!                e => Err(e.into()),
            }
        }
    };
}

If current programs rely on the return value of these functions to be UNSUPPORTED_SYSVAR, they might break in the case an unexpected value is returned. We would suggest keeping the behaviour consistent with the old program, by always returning the UNSUPPORTED_SYSVAR where appropriate.

Zellic © 2025Back to top ↑