From 4d4dddcaeacd60b248b5f4e4806374d2b9f3a1d4 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Thu, 11 May 2023 15:48:13 +0900 Subject: [PATCH] Update to nightly rustc to 2023-04-19 (#31381) * Update to nightly rustc to 2023-04-19 * pray... * Not enough pray.. * skip check... * hope merciful shellcheck * ci hack... * Restore ci/test-checks.sh * Restore debug_assertions with proper workaround... * small cleanup * seems this isn't needed? * Make the workaround more robust... * Remove now-resolved clippy exception --- ci/rust-version.sh | 2 +- ci/test-checks.sh | 2 +- programs/bpf_loader/src/serialization.rs | 82 +++++++++++++------ .../src/zk_token_proof_instruction.rs | 2 +- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/ci/rust-version.sh b/ci/rust-version.sh index 7bb8a3914f0568..2b43b606de03aa 100644 --- a/ci/rust-version.sh +++ b/ci/rust-version.sh @@ -29,7 +29,7 @@ fi if [[ -n $RUST_NIGHTLY_VERSION ]]; then nightly_version="$RUST_NIGHTLY_VERSION" else - nightly_version=2023-03-04 + nightly_version=2023-04-19 fi diff --git a/ci/test-checks.sh b/ci/test-checks.sh index 04919cd132fd8a..a2ea2a6c24b9ac 100755 --- a/ci/test-checks.sh +++ b/ci/test-checks.sh @@ -75,7 +75,7 @@ fi _ ci/order-crates-for-publishing.py -nightly_clippy_allows=() +nightly_clippy_allows=(--allow=clippy::redundant_clone) # run nightly clippy for `sdk/` as there's a moderate amount of nightly-only code there _ scripts/cargo-for-all-lock-files.sh -- "+${rust_nightly}" clippy --workspace --all-targets --features dummy-for-ci-check -- \ diff --git a/programs/bpf_loader/src/serialization.rs b/programs/bpf_loader/src/serialization.rs index 7a36a5229d95ea..40dcc0ad9773d2 100644 --- a/programs/bpf_loader/src/serialization.rs +++ b/programs/bpf_loader/src/serialization.rs @@ -563,6 +563,7 @@ mod tests { }, std::{ cell::RefCell, + mem::transmute, rc::Rc, slice::{self, from_raw_parts, from_raw_parts_mut}, }, @@ -994,58 +995,94 @@ mod tests { } // the old bpf_loader in-program deserializer bpf_loader::id() - #[allow(clippy::type_complexity)] + #[deny(unsafe_op_in_unsafe_fn)] pub unsafe fn deserialize_unaligned<'a>( input: *mut u8, ) -> (&'a Pubkey, Vec>, &'a [u8]) { + // this boring boilerplate struct is needed until inline const... + struct Ptr(std::marker::PhantomData); + impl Ptr { + const COULD_BE_UNALIGNED: bool = std::mem::align_of::() > 1; + + #[inline(always)] + fn read_possibly_unaligned(input: *mut u8, offset: usize) -> T { + unsafe { + let src = input.add(offset) as *const T; + if Self::COULD_BE_UNALIGNED { + src.read_unaligned() + } else { + src.read() + } + } + } + + // rustc inserts debug_assert! for misaligned pointer dereferences when + // deserializing, starting from [1]. so, use std::mem::transmute as the last resort + // while preventing clippy from complaining to suggest not to use it. + // [1]: https://github.com/rust-lang/rust/commit/22a7a19f9333bc1fcba97ce444a3515cb5fb33e6 + // as for the ub nature of the misaligned pointer dereference, this is + // acceptable in this code, given that this is cfg(test) and it's cared only with + // x86-64 and the target only incurs some performance penalty, not like segfaults + // in other targets. + #[inline(always)] + fn ref_possibly_unaligned<'a>(input: *mut u8, offset: usize) -> &'a T { + #[allow(clippy::transmute_ptr_to_ref)] + unsafe { + transmute(input.add(offset) as *const T) + } + } + + // See ref_possibly_unaligned's comment + #[inline(always)] + fn mut_possibly_unaligned<'a>(input: *mut u8, offset: usize) -> &'a mut T { + #[allow(clippy::transmute_ptr_to_ref)] + unsafe { + transmute(input.add(offset) as *mut T) + } + } + } + let mut offset: usize = 0; // number of accounts present - #[allow(clippy::cast_ptr_alignment)] - let num_accounts = *(input.add(offset) as *const u64) as usize; + let num_accounts = Ptr::::read_possibly_unaligned(input, offset) as usize; offset += size_of::(); // account Infos let mut accounts = Vec::with_capacity(num_accounts); for _ in 0..num_accounts { - let dup_info = *(input.add(offset) as *const u8); + let dup_info = Ptr::::read_possibly_unaligned(input, offset); offset += size_of::(); if dup_info == NON_DUP_MARKER { - #[allow(clippy::cast_ptr_alignment)] - let is_signer = *(input.add(offset) as *const u8) != 0; + let is_signer = Ptr::::read_possibly_unaligned(input, offset) != 0; offset += size_of::(); - #[allow(clippy::cast_ptr_alignment)] - let is_writable = *(input.add(offset) as *const u8) != 0; + let is_writable = Ptr::::read_possibly_unaligned(input, offset) != 0; offset += size_of::(); - let key: &Pubkey = &*(input.add(offset) as *const Pubkey); + let key = Ptr::::ref_possibly_unaligned(input, offset); offset += size_of::(); - #[allow(clippy::cast_ptr_alignment)] - let lamports = Rc::new(RefCell::new(&mut *(input.add(offset) as *mut u64))); + let lamports = Rc::new(RefCell::new(Ptr::mut_possibly_unaligned(input, offset))); offset += size_of::(); - #[allow(clippy::cast_ptr_alignment)] - let data_len = *(input.add(offset) as *const u64) as usize; + let data_len = Ptr::::read_possibly_unaligned(input, offset) as usize; offset += size_of::(); - let data = Rc::new(RefCell::new({ + let data = Rc::new(RefCell::new(unsafe { from_raw_parts_mut(input.add(offset), data_len) })); offset += data_len; - let owner: &Pubkey = &*(input.add(offset) as *const Pubkey); + let owner: &Pubkey = Ptr::::ref_possibly_unaligned(input, offset); offset += size_of::(); - #[allow(clippy::cast_ptr_alignment)] - let executable = *(input.add(offset) as *const u8) != 0; + let executable = Ptr::::read_possibly_unaligned(input, offset) != 0; offset += size_of::(); - #[allow(clippy::cast_ptr_alignment)] - let rent_epoch = *(input.add(offset) as *const u64); + let rent_epoch = Ptr::::read_possibly_unaligned(input, offset); offset += size_of::(); accounts.push(AccountInfo { @@ -1066,16 +1103,15 @@ mod tests { // instruction data - #[allow(clippy::cast_ptr_alignment)] - let instruction_data_len = *(input.add(offset) as *const u64) as usize; + let instruction_data_len = Ptr::::read_possibly_unaligned(input, offset) as usize; offset += size_of::(); - let instruction_data = { from_raw_parts(input.add(offset), instruction_data_len) }; + let instruction_data = unsafe { from_raw_parts(input.add(offset), instruction_data_len) }; offset += instruction_data_len; // program Id - let program_id: &Pubkey = &*(input.add(offset) as *const Pubkey); + let program_id = Ptr::::ref_possibly_unaligned(input, offset); (program_id, accounts, instruction_data) } diff --git a/zk-token-sdk/src/zk_token_proof_instruction.rs b/zk-token-sdk/src/zk_token_proof_instruction.rs index 21d1dae975562d..b3745c2382005f 100644 --- a/zk-token-sdk/src/zk_token_proof_instruction.rs +++ b/zk-token-sdk/src/zk_token_proof_instruction.rs @@ -1,4 +1,4 @@ -///! Instructions provided by the ZkToken Proof program +//! Instructions provided by the ZkToken Proof program pub use crate::instruction::*; use { bytemuck::bytes_of,