diff --git a/.github/workflows/blobby.yml b/.github/workflows/blobby.yml index 99afbe29..ae54ad91 100644 --- a/.github/workflows/blobby.yml +++ b/.github/workflows/blobby.yml @@ -2,9 +2,9 @@ name: blobby on: pull_request: - paths: - - "blobby/**" - - "Cargo.*" + paths: + - "blobby/**" + - "Cargo.*" push: branches: master @@ -38,11 +38,4 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo test - - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 3e256432..f66d4713 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -2,9 +2,9 @@ name: block-buffer on: pull_request: - paths: - - "block-buffer/**" - - "Cargo.*" + paths: + - "block-buffer/**" + - "Cargo.*" push: branches: master @@ -44,10 +44,11 @@ jobs: targets: ${{ matrix.target }} - run: cargo build --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} test: runs-on: ubuntu-latest diff --git a/.github/workflows/block-padding.yml b/.github/workflows/block-padding.yml index af535452..a4f77020 100644 --- a/.github/workflows/block-padding.yml +++ b/.github/workflows/block-padding.yml @@ -2,9 +2,9 @@ name: block-padding on: pull_request: - paths: - - "block-padding/**" - - "Cargo.*" + paths: + - "block-padding/**" + - "Cargo.*" push: branches: master @@ -44,10 +44,11 @@ jobs: targets: ${{ matrix.target }} - run: cargo build --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} test: runs-on: ubuntu-latest diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index 45ce9751..fed4e587 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -26,10 +26,11 @@ concurrency: cancel-in-progress: true jobs: - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} build: runs-on: ubuntu-latest diff --git a/.github/workflows/cpufeatures.yml b/.github/workflows/cpufeatures.yml index 34143af1..1dd37a57 100644 --- a/.github/workflows/cpufeatures.yml +++ b/.github/workflows/cpufeatures.yml @@ -25,10 +25,11 @@ concurrency: cancel-in-progress: true jobs: - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} # Linux tests linux: @@ -56,8 +57,6 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: ${{ matrix.deps }} - run: cargo test --target ${{ matrix.target }} @@ -76,8 +75,6 @@ jobs: with: toolchain: ${{ matrix.toolchain }} targets: x86_64-apple-darwin - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo test # Windows tests @@ -98,8 +95,6 @@ jobs: with: toolchain: ${{ matrix.toolchain }} targets: ${{ matrix.target }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo test --target ${{ matrix.target }} # Cross-compiled tests @@ -121,8 +116,6 @@ jobs: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - uses: RustCrypto/actions/cross-install@master - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cross test --target ${{ matrix.target }} # Build-only tests diff --git a/.github/workflows/dbl.yml b/.github/workflows/dbl.yml index 31f9cbec..adbdb3d4 100644 --- a/.github/workflows/dbl.yml +++ b/.github/workflows/dbl.yml @@ -45,10 +45,11 @@ jobs: targets: ${{ matrix.target }} - run: cargo build --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} test: runs-on: ubuntu-latest diff --git a/.github/workflows/hex-literal.yml b/.github/workflows/hex-literal.yml index 54a15eaf..03a9ab82 100644 --- a/.github/workflows/hex-literal.yml +++ b/.github/workflows/hex-literal.yml @@ -2,9 +2,9 @@ name: hex-literal on: pull_request: - paths: - - "hex-literal/**" - - "Cargo.*" + paths: + - "hex-literal/**" + - "Cargo.*" push: branches: master @@ -42,14 +42,13 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo build --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} test: runs-on: ubuntu-latest @@ -64,6 +63,4 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/inout.yml b/.github/workflows/inout.yml index 45ceab4b..641bef0d 100644 --- a/.github/workflows/inout.yml +++ b/.github/workflows/inout.yml @@ -2,9 +2,9 @@ name: inout on: pull_request: - paths: - - "inout/**" - - "Cargo.*" + paths: + - "inout/**" + - "Cargo.*" push: branches: master @@ -45,10 +45,11 @@ jobs: - run: cargo build --target ${{ matrix.target }} - run: cargo build --features block-padding --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} test: runs-on: ubuntu-latest diff --git a/.github/workflows/opaque-debug.yml b/.github/workflows/opaque-debug.yml index 564f51cc..f5f2ac97 100644 --- a/.github/workflows/opaque-debug.yml +++ b/.github/workflows/opaque-debug.yml @@ -2,9 +2,9 @@ name: opaque-debug on: pull_request: - paths: - - "opaque-debug/**" - - "Cargo.*" + paths: + - "opaque-debug/**" + - "Cargo.*" push: branches: master @@ -42,15 +42,8 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo build --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} - test: runs-on: ubuntu-latest strategy: @@ -64,6 +57,4 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 7403afc6..7875cd81 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -46,10 +46,11 @@ jobs: targets: ${{ matrix.target }} - run: cargo build --no-default-features --target ${{ matrix.target }} - minimal-versions: - uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master - with: - working-directory: ${{ github.workflow }} + # TODO(tarcieri): disabled until it can be made compatible with workspace-level lints + # minimal-versions: + # uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + # with: + # working-directory: ${{ github.workflow }} test: strategy: diff --git a/Cargo.toml b/Cargo.toml index 81b805fa..acd29533 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,3 +29,44 @@ opt-level = 2 [patch.crates-io] cmov = { path = "cmov" } + +[workspace.lints.clippy] +borrow_as_ptr = "warn" +cast_lossless = "warn" +cast_possible_truncation = "warn" +cast_possible_wrap = "warn" +cast_precision_loss = "warn" +cast_sign_loss = "warn" +checked_conversions = "warn" +doc_markdown = "warn" +from_iter_instead_of_collect = "warn" +manual_assert = "warn" +map_unwrap_or = "warn" +missing_errors_doc = "warn" +missing_panics_doc = "warn" +mod_module_files = "warn" +must_use_candidate = "warn" +needless_range_loop = "allow" +implicit_saturating_sub = "warn" +panic_in_result_fn = "warn" +ptr_as_ptr = "warn" +redundant_closure_for_method_calls = "warn" +ref_as_ptr = "warn" +return_self_not_must_use = "warn" +semicolon_if_nothing_returned = "warn" +trivially_copy_pass_by_ref = "warn" +std_instead_of_alloc = "warn" +std_instead_of_core = "warn" +undocumented_unsafe_blocks = "warn" +unnecessary_safety_comment = "warn" +unwrap_in_result = "warn" +unwrap_used = "warn" + +[workspace.lints.rust] +missing_copy_implementations = "warn" +missing_debug_implementations = "warn" +missing_docs = "warn" +trivial_casts = "warn" +trivial_numeric_casts = "warn" +unused_lifetimes = "warn" +unused_qualifications = "warn" diff --git a/blobby/Cargo.toml b/blobby/Cargo.toml index 5ea7538e..7e995b0e 100644 --- a/blobby/Cargo.toml +++ b/blobby/Cargo.toml @@ -13,3 +13,6 @@ description = "Iterator over simple binary blob storage" [features] alloc = [] + +[lints] +workspace = true diff --git a/blobby/src/bin/decode.rs b/blobby/src/bin/decode.rs index 1269bc01..1dd80b93 100644 --- a/blobby/src/bin/decode.rs +++ b/blobby/src/bin/decode.rs @@ -1,5 +1,5 @@ //! Encoding utility -use std::error::Error; +use core::error::Error; #[cfg(not(feature = "alloc"))] fn main() -> Result<(), Box> { diff --git a/blobby/src/bin/encode.rs b/blobby/src/bin/encode.rs index 2e0958d9..32889bbc 100644 --- a/blobby/src/bin/encode.rs +++ b/blobby/src/bin/encode.rs @@ -1,5 +1,5 @@ //! Encoding utility -use std::error::Error; +use core::error::Error; #[cfg(not(feature = "alloc"))] fn main() -> Result<(), Box> { diff --git a/blobby/src/decode.rs b/blobby/src/decode.rs index b40d7dfb..ced95a89 100644 --- a/blobby/src/decode.rs +++ b/blobby/src/decode.rs @@ -51,6 +51,7 @@ macro_rules! try_read_vlq { } /// Blobby file header +#[derive(Clone, Copy, Debug)] pub struct Header { /// Number of blobs stored in the file pub items_len: usize, @@ -59,7 +60,10 @@ pub struct Header { } impl Header { - /// Parse blobby header + /// Parse blobby header. + /// + /// # Errors + /// - If data could not be parsed successfully. pub const fn parse(data: &mut &[u8]) -> Result { match (read_vlq(data), read_vlq(data)) { (Ok(items_len), Ok(dedup_len)) => Ok(Header { @@ -72,6 +76,9 @@ impl Header { } /// Parse blobby data into an array. +/// +/// # Errors +/// - If data could not be parsed successfully. pub const fn parse_into_array( mut data: &[u8], ) -> Result<[&[u8]; ITEMS_LEN], Error> { @@ -127,7 +134,11 @@ pub const fn parse_into_array( } /// Parse blobby data into a vector of slices. +/// +/// # Errors +/// - if data failed to parse successfully #[cfg(feature = "alloc")] +#[allow(clippy::missing_panics_doc, clippy::panic_in_result_fn)] pub fn parse_into_vec(mut data: &[u8]) -> Result, Error> { use alloc::{vec, vec::Vec}; @@ -175,6 +186,7 @@ pub fn parse_into_vec(mut data: &[u8]) -> Result, Error> Ok(res) } +/// Parse data into a slice. #[macro_export] macro_rules! parse_into_slice { ($data:expr) => {{ @@ -195,6 +207,7 @@ macro_rules! parse_into_slice { }}; } +/// Parse data into structs. #[macro_export] macro_rules! parse_into_structs { ( diff --git a/blobby/src/encode.rs b/blobby/src/encode.rs index 0f0efcd9..cd055805 100644 --- a/blobby/src/encode.rs +++ b/blobby/src/encode.rs @@ -3,6 +3,7 @@ use super::{NEXT_MASK, VAL_MASK}; /// Write a git-flavoured VLQ value into `buf`. /// /// Returns the slice within `buf` that holds the value. +#[allow(clippy::cast_possible_truncation)] fn encode_vlq(mut val: usize, buf: &mut [u8; 4]) -> &[u8] { macro_rules! step { ($n:expr) => { @@ -40,6 +41,7 @@ fn encode_vlq(mut val: usize, buf: &mut [u8; 4]) -> &[u8] { /// - (J << 1) & 0x01: indicates this blob is index entry J /// - (L << 1) & 0x00: indicates an explicit blob of len L /// - (in the latter case) explicit blob contents (L bytes) +#[allow(clippy::missing_panics_doc, clippy::unwrap_used)] pub fn encode_blobs(blobs: &[T]) -> (alloc::vec::Vec, usize) where T: AsRef<[u8]>, @@ -49,7 +51,7 @@ where let mut dedup_map = BTreeMap::new(); blobs .iter() - .map(|v| v.as_ref()) + .map(AsRef::as_ref) .filter(|blob| !blob.is_empty()) .for_each(|blob| { let v = dedup_map.entry(blob.as_ref()).or_insert(0); @@ -89,7 +91,7 @@ where out_buf.extend_from_slice(e); } - for blob in blobs.iter().map(|v| v.as_ref()) { + for blob in blobs.iter().map(AsRef::as_ref) { if let Some(dup_pos) = rev_idx.get(blob) { let n = (dup_pos << 1) + 1usize; out_buf.extend_from_slice(encode_vlq(n, &mut buf)); @@ -104,6 +106,7 @@ where } #[cfg(test)] +#[allow(clippy::cast_possible_truncation, clippy::unwrap_used)] mod tests { use crate::{Error, NEXT_MASK, VAL_MASK, decode::read_vlq}; diff --git a/blobby/tests/mod.rs b/blobby/tests/mod.rs index c28d8a74..17d4ca83 100644 --- a/blobby/tests/mod.rs +++ b/blobby/tests/mod.rs @@ -1,4 +1,6 @@ +//! `blobby` tests #![cfg(feature = "alloc")] +#![allow(clippy::panic_in_result_fn)] const ITEMS_LEN: usize = 10; const DEDUP_LEN: usize = 3; @@ -15,6 +17,7 @@ const TEST_BLOBS: &[&[u8]; ITEMS_LEN] = &[ &[13; 5_000], ]; +/// Performs a round-trip test. #[test] fn blobby_rondtrip_test() -> Result<(), blobby::Error> { let (blobby_data, dedup_len) = blobby::encode_blobs(TEST_BLOBS); diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index a2c0eea8..09b32409 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -18,3 +18,6 @@ zeroize = { version = "1.4", optional = true, default-features = false } [dev-dependencies] hex-literal = "1" + +[lints] +workspace = true diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index e92cbca1..9972e26c 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -38,7 +38,7 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] -#![warn(missing_docs)] +#![allow(clippy::undocumented_unsafe_blocks)] // TODO(tarcieri): document all unsafe blocks pub use hybrid_array as array; @@ -94,12 +94,8 @@ pub struct BlockBuffer { impl BlockBuffer { /// This associated constant is used to assert block size correctness at compile time. const BLOCK_SIZE_ASSERT: bool = { - if BS::USIZE == 0 { - panic!("Block size can not be equal to zero!"); - } - if BS::USIZE > 255 { - panic!("Block size can not be bigger than 255!"); - } + assert!(BS::USIZE != 0, "Block size can not be equal to zero!"); + assert!(BS::USIZE <= 255, "Block size can not be bigger than 255!"); true }; } @@ -140,16 +136,22 @@ impl BlockBuffer { /// # Panics /// If slice length is not valid for used buffer kind. #[inline(always)] + #[must_use] + #[track_caller] pub fn new(buf: &[u8]) -> Self { - Self::try_new(buf).unwrap() + Self::try_new(buf).expect("invalid slice length for buffer kind") } /// Create new buffer from slice. /// - /// Returns an error if slice length is not valid for used buffer kind. + /// # Errors + /// - if slice length is not valid for used buffer kind. #[inline(always)] pub fn try_new(buf: &[u8]) -> Result { - assert!(Self::BLOCK_SIZE_ASSERT); + const { + assert!(Self::BLOCK_SIZE_ASSERT); + } + if !K::invariant(buf.len(), BS::USIZE) { return Err(Error); } @@ -292,7 +294,7 @@ impl BlockBuffer { #[inline(always)] unsafe fn set_pos_unchecked(&mut self, pos: usize) { debug_assert!(K::invariant(pos, BS::USIZE)); - K::set_pos(&mut self.buffer, &mut self.pos, pos) + K::set_pos(&mut self.buffer, &mut self.pos, pos); } /// Set buffer data. @@ -322,6 +324,7 @@ where Sum: ArraySize, { /// Serialize buffer into a byte array. + #[allow(clippy::missing_panics_doc)] pub fn serialize(&self) -> SerializedBuffer { let mut buf = SerializedBuffer::::default(); let data = self.get_data(); @@ -332,6 +335,9 @@ where } /// Deserialize buffer from a byte array. + /// + /// # Errors + /// - If algorithm-specific invariant fails to hold pub fn deserialize(buf: &SerializedBuffer) -> Result { let (pos, block) = buf.split_at(1); let pos = usize::from(pos[0]); @@ -366,9 +372,7 @@ impl BlockBuffer { suffix: &[u8], mut compress: impl FnMut(&Array), ) { - if suffix.len() > BS::USIZE { - panic!("suffix is too long"); - } + assert!(suffix.len() <= BS::USIZE, "suffix is too long"); let pos = self.get_pos(); let mut buf = self.pad_with_zeros(); buf[pos] = delim; diff --git a/block-buffer/src/read.rs b/block-buffer/src/read.rs index bf042af1..5300a3e9 100644 --- a/block-buffer/src/read.rs +++ b/block-buffer/src/read.rs @@ -73,6 +73,7 @@ impl ReadBuffer { /// # Safety /// `pos` must be smaller than or equal to the buffer block size and be bigger than zero. #[inline(always)] + #[allow(clippy::cast_possible_truncation)] unsafe fn set_pos_unchecked(&mut self, pos: usize) { debug_assert!(pos != 0 && pos <= BS::USIZE); self.buffer[0] = pos as u8; @@ -141,7 +142,7 @@ impl ReadBuffer { } self.write_block(tail.len(), gen_block, |tail_ks| { - tail.copy_from_slice(tail_ks) + tail.copy_from_slice(tail_ks); }); } @@ -158,6 +159,10 @@ impl ReadBuffer { } /// Deserialize buffer from a byte array. + /// + /// # Errors + /// - If the first byte is `0`. + /// - If the first byte is bigger than `BS`. #[inline] pub fn deserialize(buffer: &Array) -> Result { let pos = usize::from(buffer[0]); diff --git a/block-buffer/src/sealed.rs b/block-buffer/src/sealed.rs index 1a03ef81..bb0f9a75 100644 --- a/block-buffer/src/sealed.rs +++ b/block-buffer/src/sealed.rs @@ -43,8 +43,9 @@ impl Sealed for super::Eager { pos as usize } + #[allow(clippy::cast_possible_truncation)] fn set_pos(buf: &mut Block, _pos: &mut Self::Pos, val: usize) { - debug_assert!(val <= u8::MAX as usize); + debug_assert!(u8::try_from(val).is_ok()); // SAFETY: we write to the last byte of `buf` which is always safe unsafe { let buf_ptr = buf.as_mut_ptr().cast::(); @@ -73,8 +74,9 @@ impl Sealed for super::Lazy { *pos as usize } + #[allow(clippy::cast_possible_truncation)] fn set_pos(_: &mut Block, pos: &mut Self::Pos, val: usize) { - debug_assert!(val <= u8::MAX as usize); + debug_assert!(u8::try_from(val).is_ok()); *pos = val as u8; } diff --git a/block-buffer/tests/mod.rs b/block-buffer/tests/mod.rs index c2d09c0d..37cba977 100644 --- a/block-buffer/tests/mod.rs +++ b/block-buffer/tests/mod.rs @@ -1,3 +1,7 @@ +//! `block-buffer` tests. + +#![allow(clippy::unwrap_used)] + use block_buffer::{ EagerBuffer, LazyBuffer, ReadBuffer, array::{ diff --git a/block-padding/Cargo.toml b/block-padding/Cargo.toml index 27ea6859..e1c832da 100644 --- a/block-padding/Cargo.toml +++ b/block-padding/Cargo.toml @@ -14,3 +14,6 @@ description = "Padding and unpadding of messages divided into blocks." [dependencies] hybrid-array = "0.4.3" + +[lints] +workspace = true diff --git a/block-padding/src/lib.rs b/block-padding/src/lib.rs index 288336c1..d5d409e6 100644 --- a/block-padding/src/lib.rs +++ b/block-padding/src/lib.rs @@ -5,7 +5,6 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![deny(unsafe_code)] -#![warn(missing_docs, missing_debug_implementations)] pub use hybrid_array as array; @@ -24,7 +23,8 @@ pub trait Padding: 'static { /// Unpad data in `block`. /// - /// Returns error if the block contains malformed padding. + /// # Errors + /// - if the block contains malformed padding. fn raw_unpad(block: &[u8]) -> Result<&[u8], Error>; /// Pads `block` filled with data up to `pos` (i.e the message length @@ -40,7 +40,8 @@ pub trait Padding: 'static { /// Unpad data in `block`. /// - /// Returns error if the block contains malformed padding. + /// # Errors + /// - if the block contains malformed padding. #[inline] fn unpad(block: &Array) -> Result<&[u8], Error> { Self::raw_unpad(block.as_slice()) @@ -53,6 +54,7 @@ pub trait Padding: 'static { /// if `data` length is multiple of block size. All other padding implementations /// should always return [`PaddedData::Pad`]. #[inline] + #[must_use] fn pad_detached(data: &[u8]) -> PaddedData<'_, BlockSize> { let (blocks, tail) = Array::slice_as_chunks(data); let mut tail_block = Array::default(); @@ -64,8 +66,10 @@ pub trait Padding: 'static { /// Unpad data in `blocks` and return unpadded byte slice. /// - /// Returns error if `blocks` contain malformed padding. + /// # Errors + /// - if `blocks` contain malformed padding. #[inline] + #[allow(clippy::panic_in_result_fn)] fn unpad_blocks(blocks: &[Array]) -> Result<&[u8], Error> { let bs = BlockSize::USIZE; let (last_block, full_blocks) = blocks.split_last().ok_or(Error)?; @@ -101,9 +105,7 @@ pub struct ZeroPadding; impl Padding for ZeroPadding { #[inline] fn raw_pad(block: &mut [u8], pos: usize) { - if pos > block.len() { - panic!("`pos` is bigger than block size"); - } + assert!(pos <= block.len(), "`pos` is bigger than block size"); block[pos..].fill(0); } @@ -164,10 +166,9 @@ pub struct Pkcs7; impl Pkcs7 { #[inline] + #[allow(clippy::panic_in_result_fn)] fn unpad(block: &[u8], strict: bool) -> Result<&[u8], Error> { - if block.len() > 255 { - panic!("block size is too big for PKCS#7"); - } + assert!(block.len() <= 255, "block size is too big for PKCS#7"); let bs = block.len(); let n = block[bs - 1]; if n == 0 || n as usize > bs { @@ -183,13 +184,10 @@ impl Pkcs7 { impl Padding for Pkcs7 { #[inline] + #[allow(clippy::cast_possible_truncation)] fn raw_pad(block: &mut [u8], pos: usize) { - if block.len() > 255 { - panic!("block size is too big for PKCS#7"); - } - if pos >= block.len() { - panic!("`pos` is bigger or equal to block size"); - } + assert!(block.len() <= 255, "block size is too big for PKCS#7"); + assert!(pos < block.len(), "`pos` is bigger or equal to block size"); let n = (block.len() - pos) as u8; block[pos..].fill(n); } @@ -225,7 +223,7 @@ impl Padding for Iso10126 { fn raw_pad(block: &mut [u8], pos: usize) { // Instead of generating random bytes as specified by Iso10126 we // simply use Pkcs7 padding. - Pkcs7::raw_pad(block, pos) + Pkcs7::raw_pad(block, pos); } #[inline] @@ -255,23 +253,19 @@ pub struct AnsiX923; impl Padding for AnsiX923 { #[inline] + #[allow(clippy::cast_possible_truncation)] fn raw_pad(block: &mut [u8], pos: usize) { - if block.len() > 255 { - panic!("block size is too big for ANSI X9.23"); - } - if pos >= block.len() { - panic!("`pos` is bigger or equal to block size"); - } + assert!(block.len() <= 255, "block size is too big for ANSI X9.23"); + assert!(pos < block.len(), "`pos` is bigger or equal to block size"); let bs = block.len(); block[pos..bs - 1].fill(0); block[bs - 1] = (bs - pos) as u8; } #[inline] + #[allow(clippy::panic_in_result_fn)] fn raw_unpad(block: &[u8]) -> Result<&[u8], Error> { - if block.len() > 255 { - panic!("block size is too big for ANSI X9.23"); - } + assert!(block.len() <= 255, "block size is too big for ANSI X9.23"); let bs = block.len(); let n = block[bs - 1] as usize; if n == 0 || n > bs { @@ -306,9 +300,7 @@ pub struct Iso7816; impl Padding for Iso7816 { #[inline] fn raw_pad(block: &mut [u8], pos: usize) { - if pos >= block.len() { - panic!("`pos` is bigger or equal to block size"); - } + assert!(pos < block.len(), "`pos` is bigger or equal to block size"); block[pos] = 0x80; block[pos + 1..].fill(0); } @@ -353,9 +345,7 @@ pub struct NoPadding; impl Padding for NoPadding { #[inline] fn raw_pad(block: &mut [u8], pos: usize) { - if pos > block.len() { - panic!("`pos` is bigger than block size"); - } + assert!(pos <= block.len(), "`pos` is bigger than block size"); } #[inline] @@ -412,6 +402,9 @@ pub enum PaddedData<'a, BlockSize: ArraySize> { impl<'a, BlockSize: ArraySize> PaddedData<'a, BlockSize> { /// Unwrap the `Pad` variant. + /// + /// # Panics + /// - If `self` is a variant other than [`PaddedData::Pad`]. pub fn unwrap(self) -> (&'a [Array], Array) { match self { PaddedData::Pad { blocks, tail_block } => (blocks, tail_block), diff --git a/cmov/Cargo.toml b/cmov/Cargo.toml index b426252a..72ed9100 100644 --- a/cmov/Cargo.toml +++ b/cmov/Cargo.toml @@ -20,5 +20,8 @@ portable "best-effort" pure Rust fallback implementation. [dev-dependencies] proptest = "1.9" +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/cmov/src/lib.rs b/cmov/src/lib.rs index d15cb5a9..81782d11 100644 --- a/cmov/src/lib.rs +++ b/cmov/src/lib.rs @@ -5,30 +5,11 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" )] +#![allow(clippy::undocumented_unsafe_blocks)] // TODO(tarcieri): document all unsafe blocks #![warn( - clippy::cast_lossless, - clippy::cast_possible_truncation, - clippy::cast_precision_loss, - clippy::checked_conversions, - clippy::implicit_saturating_sub, + clippy::arithmetic_side_effects, clippy::integer_division_remainder_used, - clippy::mod_module_files, - clippy::panic, - clippy::panic_in_result_fn, - clippy::ref_as_ptr, - clippy::return_self_not_must_use, - clippy::semicolon_if_nothing_returned, - clippy::std_instead_of_alloc, - clippy::std_instead_of_core, - clippy::unwrap_used, - missing_copy_implementations, - missing_debug_implementations, - missing_docs, - rust_2018_idioms, - trivial_casts, - trivial_numeric_casts, - unused_lifetimes, - unused_qualifications + clippy::panic )] #[macro_use] @@ -163,6 +144,7 @@ macro_rules! impl_cmov_traits_for_signed_ints { $( impl Cmov for $int { #[inline] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] fn cmovnz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as $uint; tmp.cmovnz(&(*value as $uint), condition); @@ -170,6 +152,7 @@ macro_rules! impl_cmov_traits_for_signed_ints { } #[inline] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] fn cmovz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as $uint; tmp.cmovz(&(*value as $uint), condition); @@ -179,11 +162,13 @@ macro_rules! impl_cmov_traits_for_signed_ints { impl CmovEq for $int { #[inline] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { (*self as $uint).cmoveq(&(*rhs as $uint), input, output); } #[inline] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { (*self as $uint).cmovne(&(*rhs as $uint), input, output); } diff --git a/cmov/src/slice.rs b/cmov/src/slice.rs index 1592bb7a..2e43a123 100644 --- a/cmov/src/slice.rs +++ b/cmov/src/slice.rs @@ -330,15 +330,14 @@ where Word: From, { debug_assert!(size_of_val(slice) <= WORD_SIZE, "slice too large"); - slice - .iter() - .rev() - .copied() - .fold(0, |acc, n| (acc << (size_of::() * 8)) | Word::from(n)) + slice.iter().rev().copied().fold(0, |acc, n| { + (acc << (const { size_of::() * 8 })) | Word::from(n) + }) } /// Serialize [`Word`] as bytes using the same byte ordering as `slice_to_word`. #[inline] +#[allow(clippy::arithmetic_side_effects)] fn word_to_slice(word: Word, out: &mut [T]) where T: BitOrAssign + Copy + From + Shl, @@ -360,7 +359,10 @@ where #[inline] #[track_caller] #[must_use] -#[allow(clippy::integer_division_remainder_used)] +#[allow( + clippy::arithmetic_side_effects, + clippy::integer_division_remainder_used +)] fn slice_as_chunks(slice: &[T]) -> (&[[T; N]], &[T]) { assert!(N != 0, "chunk size must be non-zero"); let len_rounded_down = slice.len() / N * N; @@ -378,7 +380,10 @@ fn slice_as_chunks(slice: &[T]) -> (&[[T; N]], &[T]) { #[inline] #[track_caller] #[must_use] -#[allow(clippy::integer_division_remainder_used)] +#[allow( + clippy::arithmetic_side_effects, + clippy::integer_division_remainder_used +)] fn slice_as_chunks_mut(slice: &mut [T]) -> (&mut [[T; N]], &mut [T]) { assert!(N != 0, "chunk size must be non-zero"); let len_rounded_down = slice.len() / N * N; @@ -396,9 +401,12 @@ fn slice_as_chunks_mut(slice: &mut [T]) -> (&mut [[T; N]], &m #[inline] #[must_use] #[track_caller] -#[allow(clippy::integer_division_remainder_used)] +#[allow( + clippy::arithmetic_side_effects, + clippy::integer_division_remainder_used +)] unsafe fn slice_as_chunks_unchecked(slice: &[T]) -> &[[T; N]] { - // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length + // Caller must guarantee that `N` is nonzero and exactly divides the slice length const { debug_assert!(N != 0) }; debug_assert_eq!(slice.len() % N, 0); let new_len = slice.len() / N; @@ -413,9 +421,12 @@ unsafe fn slice_as_chunks_unchecked(slice: &[T]) -> &[[T; N]] #[inline] #[must_use] #[track_caller] -#[allow(clippy::integer_division_remainder_used)] +#[allow( + clippy::arithmetic_side_effects, + clippy::integer_division_remainder_used +)] unsafe fn slice_as_chunks_unchecked_mut(slice: &mut [T]) -> &mut [[T; N]] { - // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length + // Caller must guarantee that `N` is nonzero and exactly divides the slice length const { debug_assert!(N != 0) }; debug_assert_eq!(slice.len() % N, 0); let new_len = slice.len() / N; diff --git a/cmov/tests/core_impls.rs b/cmov/tests/core_impls.rs index 49d47e05..ac20898b 100644 --- a/cmov/tests/core_impls.rs +++ b/cmov/tests/core_impls.rs @@ -1,3 +1,7 @@ +//! Tests for `cmov` trait impls on core types. + +#![allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + /// Write the tests for an integer type, given two unequal integers macro_rules! int_tests { ($int:ident, $a:expr, $b:expr) => { diff --git a/cmov/tests/proptests.rs b/cmov/tests/proptests.rs index 2eaa911b..adb6f15f 100644 --- a/cmov/tests/proptests.rs +++ b/cmov/tests/proptests.rs @@ -1,3 +1,5 @@ +//! `cmov` property-based tests: randomized with shrinking. + /// Write the proptests for an integer type. macro_rules! int_proptests { ( $($int:ident),+ ) => { diff --git a/collectable/Cargo.toml b/collectable/Cargo.toml index 899773a0..c246cd39 100644 --- a/collectable/Cargo.toml +++ b/collectable/Cargo.toml @@ -13,3 +13,6 @@ description = "Fallible, no_std-friendly collection traits" [features] alloc = [] + +[lints] +workspace = true diff --git a/collectable/src/lib.rs b/collectable/src/lib.rs index 9d2d693a..a942411a 100644 --- a/collectable/src/lib.rs +++ b/collectable/src/lib.rs @@ -8,6 +8,7 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] +#![allow(clippy::missing_errors_doc)] #[cfg(feature = "alloc")] extern crate alloc; @@ -100,6 +101,7 @@ pub trait TryPush { /// [`TryCollect`] is an extension to [`Iterator`] which allows for performing /// a fallible collection into a collection type. pub trait TryCollect { + /// Attempt to collect into the given type. fn try_collect(&mut self) -> Result where B: TryFromIterator; diff --git a/cpubits/Cargo.toml b/cpubits/Cargo.toml index 946266cc..f8940438 100644 --- a/cpubits/Cargo.toml +++ b/cpubits/Cargo.toml @@ -14,3 +14,6 @@ Compile-time detection heuristics for the optimal word size to use for the target CPU, which in some cases may differ from its address size a.k.a. `target_pointer_width`. Implemented as `macro_rules!` """ + +[lints] +workspace = true diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index c29837e0..0622d7a6 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -26,3 +26,6 @@ libc = { version = "0.2.155", default-features = false } [target.'cfg(all(target_arch = "aarch64", target_os = "android"))'.dependencies] libc = { version = "0.2.155", default-features = false } + +[lints] +workspace = true diff --git a/cpufeatures/README.md b/cpufeatures/README.md index 0191afb0..9aace519 100644 --- a/cpufeatures/README.md +++ b/cpufeatures/README.md @@ -73,7 +73,7 @@ Target features: ### `loongarch64` -Linux only (LoongArch64 does not support OS-independent feature detection) +Linux only (`loongarch64` does not support OS-independent feature detection) Target features: diff --git a/cpufeatures/src/aarch64.rs b/cpufeatures/src/aarch64.rs index 690fe221..c1980108 100644 --- a/cpufeatures/src/aarch64.rs +++ b/cpufeatures/src/aarch64.rs @@ -131,7 +131,13 @@ macro_rules! check { } /// Apple helper function for calling `sysctlbyname`. +/// +/// +/// +/// # Panics +/// - if `name` is not NUL terminated #[cfg(target_vendor = "apple")] +#[must_use] pub unsafe fn sysctlbyname(name: &[u8]) -> bool { assert_eq!( name.last().cloned(), @@ -141,13 +147,21 @@ pub unsafe fn sysctlbyname(name: &[u8]) -> bool { ); let mut value: u32 = 0; - let mut size = core::mem::size_of::(); + let mut size = size_of::(); + // SAFETY: + // - `name` is being cast from a valid byte slice we asserted was NUL terminated above. + // - `value` is a properly-aligned, writable integer. + // - `size` is initialized to the size of `value` (4-bytes). + // - The last two arguments,`newp` and `newlen`, are for setting system parameters, which we + // aren't doing here (and requires root privileges). The docs say the following: + // - `newp`: "Specify NULL if you don’t want to set the attribute’s value" + // - `newlen`: "Specify 0 if you don’t want to set the attribute’s value" let rc = unsafe { libc::sysctlbyname( - name.as_ptr() as *const i8, - &mut value as *mut _ as *mut libc::c_void, - &mut size, + name.as_ptr().cast::(), + (&raw mut value).cast::(), + &raw mut size, core::ptr::null_mut(), 0, ) diff --git a/cpufeatures/tests/loongarch64.rs b/cpufeatures/tests/loongarch64.rs index 8ca6e921..2e40990c 100644 --- a/cpufeatures/tests/loongarch64.rs +++ b/cpufeatures/tests/loongarch64.rs @@ -1,4 +1,4 @@ -//! LoongArch64 tests +//! `loongarch64` tests #![cfg(target_arch = "loongarch64")] diff --git a/cpufeatures/tests/x86.rs b/cpufeatures/tests/x86.rs index 0d812423..8b1692b2 100644 --- a/cpufeatures/tests/x86.rs +++ b/cpufeatures/tests/x86.rs @@ -1,4 +1,4 @@ -//! x86/x86_64 tests +//! `x86`/`x86_64` tests #![cfg(any(target_arch = "x86", target_arch = "x86_64"))] diff --git a/ctutils/Cargo.toml b/ctutils/Cargo.toml index c34efb08..f86dcfe2 100644 --- a/ctutils/Cargo.toml +++ b/ctutils/Cargo.toml @@ -29,5 +29,8 @@ proptest = "1.9" alloc = [] subtle = ["dep:subtle"] +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/ctutils/src/choice.rs b/ctutils/src/choice.rs index 0700da34..f93014d2 100644 --- a/ctutils/src/choice.rs +++ b/ctutils/src/choice.rs @@ -108,7 +108,9 @@ impl Choice { /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise. #[inline] #[must_use] + #[allow(clippy::cast_sign_loss)] pub const fn from_i64_eq(x: i64, y: i64) -> Self { + // TODO(tarcieri): use `cast_unsigned` when MSRV is 1.87 Self::from_u64_nz(x as u64 ^ y as u64).not() } @@ -307,7 +309,9 @@ impl Choice { /// and can't use the trait. The former will provide better constant-time assurances. #[inline] #[must_use] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] pub const fn select_i64(self, a: i64, b: i64) -> i64 { + // TODO(tarcieri): use `cast_signed` when MSRV is 1.87 self.select_u64(a as u64, b as u64) as i64 } diff --git a/ctutils/src/ct_option.rs b/ctutils/src/ct_option.rs index 18362666..dcace64b 100644 --- a/ctutils/src/ct_option.rs +++ b/ctutils/src/ct_option.rs @@ -360,6 +360,9 @@ impl CtOption { /// This implementation doesn't intend to be constant-time nor try to protect the leakage of the /// `T` value since the [`Result`] will do it anyway. /// + /// + /// # Errors + /// - Returns `err` in the event `self.is_some()` is [`Choice::FALSE`]. #[inline] pub fn ok_or(self, err: E) -> Result { self.into_option().ok_or(err) @@ -374,7 +377,11 @@ impl CtOption { /// This implementation doesn't intend to be constant-time nor try to protect the leakage of the /// `T` value since the [`Result`] will do it anyway. /// + /// + /// # Errors + /// - Returns `err` in the event `self.is_some()` is [`Choice::FALSE`]. #[inline] + #[allow(clippy::missing_errors_doc)] pub fn ok_or_else(self, err: F) -> Result where F: FnOnce() -> E, @@ -684,6 +691,7 @@ mod tests { #[test] fn unwrap_or_macro() { // Don't actually use this! It's just a test function implemented in variable-time + #[allow(clippy::trivially_copy_pass_by_ref)] const fn select_vartime(a: &u8, b: &u8, choice: Choice) -> u8 { if choice.to_bool_vartime() { *b } else { *a } } diff --git a/ctutils/src/lib.rs b/ctutils/src/lib.rs index 3c11a82a..52f4a8c6 100644 --- a/ctutils/src/lib.rs +++ b/ctutils/src/lib.rs @@ -6,32 +6,9 @@ )] #![deny(unsafe_code)] #![warn( - clippy::borrow_as_ptr, - clippy::cast_lossless, - clippy::cast_possible_truncation, - clippy::cast_precision_loss, - clippy::checked_conversions, - clippy::implicit_saturating_sub, + clippy::arithmetic_side_effects, clippy::integer_division_remainder_used, - clippy::must_use_candidate, - clippy::mod_module_files, - clippy::panic, - clippy::panic_in_result_fn, - clippy::ref_as_ptr, - clippy::semicolon_if_nothing_returned, - clippy::std_instead_of_alloc, - clippy::std_instead_of_core, - clippy::undocumented_unsafe_blocks, - clippy::unnecessary_safety_comment, - clippy::unwrap_in_result, - missing_copy_implementations, - missing_debug_implementations, - missing_docs, - rust_2018_idioms, - trivial_casts, - trivial_numeric_casts, - unused_lifetimes, - unused_qualifications + clippy::panic )] #![cfg_attr(not(test), warn(clippy::unwrap_used))] diff --git a/ctutils/src/traits/ct_gt.rs b/ctutils/src/traits/ct_gt.rs index fcca6033..d4f0b3af 100644 --- a/ctutils/src/traits/ct_gt.rs +++ b/ctutils/src/traits/ct_gt.rs @@ -46,10 +46,14 @@ impl_ct_gt_for_nonzero_integer!(NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, N impl CtGt for cmp::Ordering { #[inline] + #[allow(clippy::arithmetic_side_effects, clippy::cast_sign_loss)] fn ct_gt(&self, other: &Self) -> Choice { // No impl of `CtGt` for `i8`, so use `u8` + // TODO(tarcieri): use `cast_signed` when MSRV is 1.87 let a = (*self as i8) + 1; let b = (*other as i8) + 1; + + // TODO(tarcieri): use `cast_unsigned` when MSRV is 1.87 (a as u8).ct_gt(&(b as u8)) } } diff --git a/ctutils/src/traits/ct_lookup.rs b/ctutils/src/traits/ct_lookup.rs index 4e87167f..bdfc6d2d 100644 --- a/ctutils/src/traits/ct_lookup.rs +++ b/ctutils/src/traits/ct_lookup.rs @@ -24,6 +24,7 @@ where type Output = T; #[inline] + #[allow(clippy::arithmetic_side_effects)] fn ct_lookup(&self, index: Idx) -> CtOption { let mut ret = CtOption::none(); let mut i = Idx::default(); diff --git a/ctutils/src/traits/ct_lt.rs b/ctutils/src/traits/ct_lt.rs index 75ea7d4f..939eac63 100644 --- a/ctutils/src/traits/ct_lt.rs +++ b/ctutils/src/traits/ct_lt.rs @@ -46,10 +46,14 @@ impl_ct_lt_for_nonzero_integer!(NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, N impl CtLt for cmp::Ordering { #[inline] + #[allow(clippy::arithmetic_side_effects, clippy::cast_sign_loss)] fn ct_lt(&self, other: &Self) -> Choice { // No impl of `CtLt` for `i8`, so use `u8` + // TODO(tarcieri): use `cast_signed` when MSRV is 1.87 let a = (*self as i8) + 1; let b = (*other as i8) + 1; + + // TODO(tarcieri): use `cast_unsigned` when MSRV is 1.87 (a as u8).ct_lt(&(b as u8)) } } diff --git a/ctutils/src/traits/ct_neg.rs b/ctutils/src/traits/ct_neg.rs index 51b9ffc0..25169adb 100644 --- a/ctutils/src/traits/ct_neg.rs +++ b/ctutils/src/traits/ct_neg.rs @@ -24,12 +24,14 @@ macro_rules! impl_signed_ct_neg { $( impl CtNeg for $int { #[inline] + #[allow(clippy::arithmetic_side_effects)] fn ct_neg(&self, choice: Choice) -> Self { let neg = -*self; self.ct_select(&neg, choice) } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn ct_neg_assign(&mut self, choice: Choice) { let neg = -*self; self.ct_assign(&neg, choice) diff --git a/ctutils/tests/proptests.rs b/ctutils/tests/proptests.rs index b6768480..5a1b24dc 100644 --- a/ctutils/tests/proptests.rs +++ b/ctutils/tests/proptests.rs @@ -1,3 +1,5 @@ +//! `cmov` property-based tests: randomized with shrinking. + /// Write the proptests for an integer type. macro_rules! int_proptests { ( $($int:ident),+ ) => { diff --git a/dbl/Cargo.toml b/dbl/Cargo.toml index 7d6f06d8..2166f7f7 100644 --- a/dbl/Cargo.toml +++ b/dbl/Cargo.toml @@ -17,3 +17,6 @@ polynomial among the irreducible degree `n` polynomials having a minimum number [dependencies] hybrid-array = "0.4" + +[lints] +workspace = true diff --git a/dbl/src/lib.rs b/dbl/src/lib.rs index 61a2d919..0b050d7e 100644 --- a/dbl/src/lib.rs +++ b/dbl/src/lib.rs @@ -4,6 +4,7 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] +#![allow(clippy::unwrap_used)] #![forbid(unsafe_code)] use hybrid_array::Array; diff --git a/hex-literal/Cargo.toml b/hex-literal/Cargo.toml index d7f75631..0b701f78 100644 --- a/hex-literal/Cargo.toml +++ b/hex-literal/Cargo.toml @@ -11,3 +11,6 @@ license = "MIT OR Apache-2.0" keywords = ["hex", "literals"] categories = ["no-std"] description = "A macro for converting hexadecimal string literals to a byte array at compile time" + +[lints] +workspace = true diff --git a/hex-literal/src/lib.rs b/hex-literal/src/lib.rs index ca97b177..46cad9d6 100644 --- a/hex-literal/src/lib.rs +++ b/hex-literal/src/lib.rs @@ -38,6 +38,7 @@ const fn next_byte(string: &[u8], pos: usize) -> Option<(u8, usize)> { /// /// This function is an implementation detail and SHOULD NOT be called directly! #[doc(hidden)] +#[must_use] pub const fn len(strings: &[&[u8]]) -> usize { let mut i = 0; let mut len = 0; @@ -56,6 +57,7 @@ pub const fn len(strings: &[&[u8]]) -> usize { /// /// This function is an implementation detail and SHOULD NOT be called directly! #[doc(hidden)] +#[must_use] pub const fn decode(strings: &[&[u8]]) -> Option<[u8; LEN]> { let mut string_pos = 0; let mut buf = [0u8; LEN]; diff --git a/hex-literal/tests/basic.rs b/hex-literal/tests/basic.rs index eb29fef4..5f5ee290 100644 --- a/hex-literal/tests/basic.rs +++ b/hex-literal/tests/basic.rs @@ -1,3 +1,5 @@ +//! Basic `hex-literal` tests. + use hex_literal::hex; #[test] diff --git a/inout/Cargo.toml b/inout/Cargo.toml index f5708bc3..7dea4f35 100644 --- a/inout/Cargo.toml +++ b/inout/Cargo.toml @@ -16,5 +16,8 @@ description = "Custom reference types for code generic over in-place and buffer- hybrid-array = "0.4" block-padding = { version = "0.4.2", path = "../block-padding", optional = true } +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/inout/src/inout.rs b/inout/src/inout.rs index f770921a..1a82000d 100644 --- a/inout/src/inout.rs +++ b/inout/src/inout.rs @@ -23,6 +23,7 @@ impl<'inp, 'out, T> InOut<'inp, 'out, T> { /// Get immutable reference to the input value. #[inline(always)] + #[must_use] pub fn get_in(&self) -> &T { unsafe { &*self.in_ptr } } @@ -39,11 +40,12 @@ impl<'inp, 'out, T> InOut<'inp, 'out, T> { /// In the case if the input and output references are the same, simply returns /// the output reference. Otherwise, copies data from the former to the latter /// before returning the output reference. + #[must_use] pub fn into_out_with_copied_in(self) -> &'out mut T where T: Copy, { - if !core::ptr::eq(self.in_ptr, self.out_ptr) { + if !ptr::eq(self.in_ptr, self.out_ptr) { unsafe { ptr::copy(self.in_ptr, self.out_ptr, 1); } @@ -53,12 +55,14 @@ impl<'inp, 'out, T> InOut<'inp, 'out, T> { /// Consume `self` and get mutable reference to the output value with lifetime `'out`. #[inline(always)] + #[must_use] pub fn into_out(self) -> &'out mut T { unsafe { &mut *self.out_ptr } } /// Convert `self` to a pair of raw input and output pointers. #[inline(always)] + #[must_use] pub fn into_raw(self) -> (*const T, *mut T) { (self.in_ptr, self.out_ptr) } @@ -94,6 +98,7 @@ impl<'inp, 'out, T> InOut<'inp, 'out, T> { impl InOut<'_, '_, T> { /// Clone input value and return it. #[inline(always)] + #[must_use] pub fn clone_in(&self) -> T { unsafe { (*self.in_ptr).clone() } } @@ -102,7 +107,7 @@ impl InOut<'_, '_, T> { impl<'a, T> From<&'a mut T> for InOut<'a, 'a, T> { #[inline(always)] fn from(val: &'a mut T) -> Self { - let p = val as *mut T; + let p = ptr::from_mut(val); Self { in_ptr: p, out_ptr: p, @@ -115,8 +120,8 @@ impl<'inp, 'out, T> From<(&'inp T, &'out mut T)> for InOut<'inp, 'out, T> { #[inline(always)] fn from((in_val, out_val): (&'inp T, &'out mut T)) -> Self { Self { - in_ptr: in_val as *const T, - out_ptr: out_val as *mut T, + in_ptr: ptr::from_ref::(in_val), + out_ptr: ptr::from_mut::(out_val), _pd: Default::default(), } } @@ -132,8 +137,8 @@ impl<'inp, 'out, T, N: ArraySize> InOut<'inp, 'out, Array> { assert!(pos < N::USIZE); unsafe { InOut { - in_ptr: (self.in_ptr as *const T).add(pos), - out_ptr: (self.out_ptr as *mut T).add(pos), + in_ptr: self.in_ptr.cast::().add(pos), + out_ptr: self.out_ptr.cast::().add(pos), _pd: PhantomData, } } @@ -141,10 +146,11 @@ impl<'inp, 'out, T, N: ArraySize> InOut<'inp, 'out, Array> { /// Convert `InOut` array to `InOutBuf`. #[inline(always)] + #[must_use] pub fn into_buf(self) -> InOutBuf<'inp, 'out, T> { InOutBuf { - in_ptr: self.in_ptr as *const T, - out_ptr: self.out_ptr as *mut T, + in_ptr: self.in_ptr.cast::(), + out_ptr: self.out_ptr.cast::(), len: N::USIZE, _pd: PhantomData, } @@ -180,7 +186,6 @@ impl InOut<'_, '_, Array> { /// # Panics /// If `data` length is not equal to the buffer length. #[inline(always)] - #[allow(clippy::needless_range_loop)] pub fn xor_in2out(&mut self, data: &Array) { unsafe { let input = ptr::read(self.in_ptr); @@ -204,7 +209,6 @@ where /// # Panics /// If `data` length is not equal to the buffer length. #[inline(always)] - #[allow(clippy::needless_range_loop)] pub fn xor_in2out(&mut self, data: &Array, M>) { unsafe { let input = ptr::read(self.in_ptr); diff --git a/inout/src/inout_buf.rs b/inout/src/inout_buf.rs index 5b479c4d..4d62fae6 100644 --- a/inout/src/inout_buf.rs +++ b/inout/src/inout_buf.rs @@ -2,7 +2,7 @@ use crate::{ InOut, errors::{IntoArrayError, NotEqualError}, }; -use core::{marker::PhantomData, slice}; +use core::{marker::PhantomData, ptr, slice}; use hybrid_array::{Array, ArraySize}; /// Custom slice type which references one immutable (input) slice and one @@ -32,7 +32,7 @@ impl<'a, T> InOutBuf<'a, 'a, T> { /// Create `InOutBuf` from a single mutable reference. #[inline(always)] pub fn from_mut(val: &'a mut T) -> InOutBuf<'a, 'a, T> { - let p = val as *mut T; + let p = ptr::from_mut(val); Self { in_ptr: p, out_ptr: p, @@ -57,8 +57,8 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { #[inline(always)] pub fn from_ref_mut(in_val: &'inp T, out_val: &'out mut T) -> Self { Self { - in_ptr: in_val as *const T, - out_ptr: out_val as *mut T, + in_ptr: ptr::from_ref::(in_val), + out_ptr: ptr::from_mut::(out_val), len: 1, _pd: PhantomData, } @@ -66,7 +66,8 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// Create `InOutBuf` from immutable and mutable slices. /// - /// Returns an error if length of slices is not equal to each other. + /// # Errors + /// - if length of slices is not equal to each other. #[inline(always)] pub fn new(in_buf: &'inp [T], out_buf: &'out mut [T]) -> Result { if in_buf.len() != out_buf.len() { @@ -83,12 +84,14 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// Get length of the inner buffers. #[inline(always)] + #[must_use] pub fn len(&self) -> usize { self.len } /// Returns `true` if the buffer has a length of 0. #[inline(always)] + #[must_use] pub fn is_empty(&self) -> bool { self.len == 0 } @@ -111,6 +114,7 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// Get input slice. #[inline(always)] + #[must_use] pub fn get_in(&self) -> &[T] { unsafe { slice::from_raw_parts(self.in_ptr, self.len) } } @@ -127,13 +131,14 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// In the case if the input and output slices point to the same memory, simply returns /// the output slice. Otherwise, copies data from the former to the latter /// before returning the output slice. + #[must_use] pub fn into_out_with_copied_in(self) -> &'out mut [T] where T: Copy, { - if !core::ptr::eq(self.in_ptr, self.out_ptr) { + if !ptr::eq(self.in_ptr, self.out_ptr) { unsafe { - core::ptr::copy(self.in_ptr, self.out_ptr, self.len); + ptr::copy(self.in_ptr, self.out_ptr, self.len); } } unsafe { slice::from_raw_parts_mut(self.out_ptr, self.len) } @@ -141,12 +146,14 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// Consume `self` and get output slice with lifetime `'out`. #[inline(always)] + #[must_use] pub fn into_out(self) -> &'out mut [T] { unsafe { slice::from_raw_parts_mut(self.out_ptr, self.len) } } /// Get raw input and output pointers. #[inline(always)] + #[must_use] pub fn into_raw(self) -> (*const T, *mut T) { (self.in_ptr, self.out_ptr) } @@ -206,6 +213,7 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// /// Panics if `mid > len`. #[inline(always)] + #[must_use] pub fn split_at(self, mid: usize) -> (InOutBuf<'inp, 'out, T>, InOutBuf<'inp, 'out, T>) { assert!(mid <= self.len); let (tail_in_ptr, tail_out_ptr) = unsafe { (self.in_ptr.add(mid), self.out_ptr.add(mid)) }; @@ -227,6 +235,7 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { /// Partition buffer into 2 parts: buffer of arrays and tail. #[inline(always)] + #[must_use] pub fn into_chunks( self, ) -> (InOutBuf<'inp, 'out, Array>, InOutBuf<'inp, 'out, T>) { @@ -235,8 +244,8 @@ impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> { let tail_len = self.len() - tail_pos; unsafe { let chunks = InOutBuf { - in_ptr: self.in_ptr as *const Array, - out_ptr: self.out_ptr as *mut Array, + in_ptr: self.in_ptr.cast::>(), + out_ptr: self.out_ptr.cast::>(), len: chunks, _pd: PhantomData, }; @@ -258,7 +267,6 @@ impl InOutBuf<'_, '_, u8> { /// # Panics /// If `data` length is not equal to the buffer length. #[inline(always)] - #[allow(clippy::needless_range_loop)] pub fn xor_in2out(&mut self, data: &[u8]) { assert_eq!(self.len(), data.len()); unsafe { @@ -281,8 +289,8 @@ where fn try_into(self) -> Result>, Self::Error> { if self.len() == N::USIZE { Ok(InOut { - in_ptr: self.in_ptr as *const _, - out_ptr: self.out_ptr as *mut _, + in_ptr: self.in_ptr.cast(), + out_ptr: self.out_ptr.cast(), _pd: PhantomData, }) } else { diff --git a/inout/src/lib.rs b/inout/src/lib.rs index 8adc0d7a..b9c8336e 100644 --- a/inout/src/lib.rs +++ b/inout/src/lib.rs @@ -7,7 +7,8 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg" )] #![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_docs)] +#![allow(missing_debug_implementations)] // TODO(tarcieri): add missing `Debug` impls +#![allow(clippy::undocumented_unsafe_blocks)] // TODO(tarcieri): document all unsafe blocks #[cfg(feature = "block-padding")] pub use block_padding; diff --git a/inout/src/reserved.rs b/inout/src/reserved.rs index 95152c17..e466e63a 100644 --- a/inout/src/reserved.rs +++ b/inout/src/reserved.rs @@ -22,6 +22,9 @@ pub struct InOutBufReserved<'inp, 'out, T> { impl<'a, T> InOutBufReserved<'a, 'a, T> { /// Crate [`InOutBufReserved`] from a single mutable slice. + /// + /// # Errors + /// - if `out` is too small. pub fn from_mut_slice(buf: &'a mut [T], msg_len: usize) -> Result { if msg_len > buf.len() { return Err(OutIsTooSmallError); @@ -78,18 +81,21 @@ impl InOutBufReserved<'_, '_, T> { /// Get raw input and output pointers. #[inline(always)] + #[must_use] pub fn into_raw(self) -> (*const T, *mut T) { (self.in_ptr, self.out_ptr) } /// Get input buffer length. #[inline(always)] + #[must_use] pub fn get_in_len(&self) -> usize { self.in_len } /// Get output buffer length. #[inline(always)] + #[must_use] pub fn get_out_len(&self) -> usize { self.out_len } @@ -114,6 +120,9 @@ impl InOutBufReserved<'_, '_, T> { impl<'inp, 'out, T> InOutBufReserved<'inp, 'out, T> { /// Crate [`InOutBufReserved`] from two separate slices. + /// + /// # Errors + /// - if `out` is too small. pub fn from_slices( in_buf: &'inp [T], out_buf: &'out mut [T], @@ -132,6 +141,7 @@ impl<'inp, 'out, T> InOutBufReserved<'inp, 'out, T> { /// Get input slice. #[inline(always)] + #[must_use] pub fn get_in(&self) -> &[T] { unsafe { slice::from_raw_parts(self.in_ptr, self.in_len) } } @@ -144,6 +154,7 @@ impl<'inp, 'out, T> InOutBufReserved<'inp, 'out, T> { /// Consume `self` and get output slice with lifetime `'out`. #[inline(always)] + #[must_use] pub fn into_out(self) -> &'out mut [T] { unsafe { slice::from_raw_parts_mut(self.out_ptr, self.out_len) } } @@ -152,7 +163,11 @@ impl<'inp, 'out, T> InOutBufReserved<'inp, 'out, T> { #[cfg(feature = "block-padding")] impl<'inp, 'out> InOutBufReserved<'inp, 'out, u8> { /// Transform buffer into [`PaddedInOutBuf`] using padding algorithm `P`. + /// + /// # Errors + /// - if the padding is invalid #[inline(always)] + #[allow(clippy::missing_panics_doc, clippy::panic_in_result_fn)] pub fn into_padded_blocks(self) -> Result, PadError> where P: Padding, diff --git a/inout/tests/split-inout.rs b/inout/tests/split-inout.rs index c637fb92..7628b530 100644 --- a/inout/tests/split-inout.rs +++ b/inout/tests/split-inout.rs @@ -1,3 +1,5 @@ +//! Tests for splitting `InOutBuf`. + use hybrid_array::{ Array, sizes::{U2, U4, U8}, diff --git a/opaque-debug/Cargo.toml b/opaque-debug/Cargo.toml index 3992b9e6..a4f15622 100644 --- a/opaque-debug/Cargo.toml +++ b/opaque-debug/Cargo.toml @@ -9,3 +9,6 @@ readme = "README.md" repository = "https://github.com/RustCrypto/utils" license = "MIT OR Apache-2.0" description = "Macro for opaque Debug trait implementation" + +[lints] +workspace = true diff --git a/opaque-debug/tests/mod.rs b/opaque-debug/tests/mod.rs index 9def4c93..4db2b5ac 100644 --- a/opaque-debug/tests/mod.rs +++ b/opaque-debug/tests/mod.rs @@ -1,3 +1,5 @@ +//! `opaque-debug` tests + #![allow(dead_code)] struct Foo { diff --git a/wycheproof2blb/src/aead.rs b/wycheproof2blb/src/aead.rs index b06fee43..49ac8116 100644 --- a/wycheproof2blb/src/aead.rs +++ b/wycheproof2blb/src/aead.rs @@ -42,14 +42,17 @@ pub struct TestCase { pub tag: Vec, } +#[must_use] pub fn aes_gcm_generator(data: &[u8], algorithm: &str, key_size: u32) -> Vec { generator(data, algorithm, key_size, 12 * 8) } +#[must_use] pub fn chacha20_poly1305(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { generator(data, algorithm, 256, 12 * 8) } +#[must_use] pub fn xchacha20_poly1305(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { generator(data, algorithm, 256, 24 * 8) } diff --git a/wycheproof2blb/src/ecdsa.rs b/wycheproof2blb/src/ecdsa.rs index 5e3973a6..df5399ee 100644 --- a/wycheproof2blb/src/ecdsa.rs +++ b/wycheproof2blb/src/ecdsa.rs @@ -60,7 +60,7 @@ pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec "SHA-224" | "SHA-256" | "SHA-384" | "SHA-512" )); for tc in &g.tests { - if tc.case.result == crate::wycheproof::CaseResult::Acceptable { + if tc.case.result == wycheproof::CaseResult::Acceptable { // TODO: figure out what to do with test cases that pass but which have weak params continue; } diff --git a/wycheproof2blb/src/hkdf.rs b/wycheproof2blb/src/hkdf.rs index f8ab7580..43228bd6 100644 --- a/wycheproof2blb/src/hkdf.rs +++ b/wycheproof2blb/src/hkdf.rs @@ -44,7 +44,7 @@ pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec let mut infos = vec![]; for g in &suite.test_groups { for tc in &g.tests { - if tc.case.result != crate::wycheproof::CaseResult::Valid { + if tc.case.result != wycheproof::CaseResult::Valid { continue; } if tc.okm.len() != tc.size { diff --git a/wycheproof2blb/src/mac.rs b/wycheproof2blb/src/mac.rs index f52e6db6..d51b7572 100644 --- a/wycheproof2blb/src/mac.rs +++ b/wycheproof2blb/src/mac.rs @@ -34,6 +34,7 @@ pub struct TestCase { pub tag: Vec, } +#[must_use] pub fn generator(data: &[u8], algorithm: &str, key_size: u32) -> Vec { let suite: TestSuite = serde_json::from_slice(data).unwrap(); assert_eq!(algorithm, suite.suite.algorithm); diff --git a/wycheproof2blb/src/main.rs b/wycheproof2blb/src/main.rs index d30932ec..c7a61da3 100644 --- a/wycheproof2blb/src/main.rs +++ b/wycheproof2blb/src/main.rs @@ -3,6 +3,7 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] + use std::io::Write; // `pub mod` is used to silence "field is never read" warnings diff --git a/wycheproof2blb/src/wycheproof.rs b/wycheproof2blb/src/wycheproof.rs index aab2a9e5..50b80f15 100644 --- a/wycheproof2blb/src/wycheproof.rs +++ b/wycheproof2blb/src/wycheproof.rs @@ -36,8 +36,8 @@ pub enum CaseResult { Acceptable, } -impl std::fmt::Display for CaseResult { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for CaseResult { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "{}", diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index d5077c08..f9943939 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -31,5 +31,8 @@ aarch64 = [] # NOTE: vestigial no-op feature; AArch64 support is always enabled derive = ["zeroize_derive"] simd = [] # NOTE: MSRV 1.72 +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/zeroize/src/barrier.rs b/zeroize/src/barrier.rs index ae297e3b..d61abc5a 100644 --- a/zeroize/src/barrier.rs +++ b/zeroize/src/barrier.rs @@ -68,7 +68,7 @@ pub fn optimization_barrier(val: &T) { unsafe { core::arch::asm!( "# {}", - in(reg) val as *const T as *const (), + in(reg) core::ptr::from_ref::(val).cast::<()>(), options(readonly, preserves_flags, nostack), ); } @@ -96,7 +96,7 @@ pub fn optimization_barrier(val: &T) { core::hint::black_box(val); if size_of_val(val) > 0 { - custom_black_box(val as *const T as *const u8); + custom_black_box(core::ptr::from_ref(val).cast::()); } } } diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 0fb628e6..7d2dec64 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -4,7 +4,7 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] -#![warn(missing_docs, unused_qualifications)] +#![allow(clippy::undocumented_unsafe_blocks)] // TODO(tarcieri): document all unsafe blocks //! Securely zero memory with a simple trait ([`Zeroize`]) built on stable Rust //! primitives which guarantee the operation will not be "optimized away". @@ -30,11 +30,10 @@ //! //! ## Minimum Supported Rust Version //! -//! Requires Rust **1.72** or newer. +//! Requires Rust **1.85** or newer. //! -//! In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope -//! for this crate's SemVer guarantees), however when we do it will be accompanied -//! by a minor version bump. +//! In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope for this crate's +//! semantic versioning guarantees). //! //! ## Usage //! @@ -323,10 +322,10 @@ impl_zeroize_with_default! { u8, u16, u32, u64, u128, usize } -/// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation. +/// `PhantomPinned` is zero sized so provide a `ZeroizeOnDrop` implementation. impl ZeroizeOnDrop for PhantomPinned {} -/// `()` is zero sized so provide a ZeroizeOnDrop implementation. +/// `()` is zero sized so provide a `ZeroizeOnDrop` implementation. impl ZeroizeOnDrop for () {} macro_rules! impl_zeroize_for_non_zero { @@ -417,7 +416,11 @@ where // The memory pointed to by `self` is valid for `size_of::()` bytes. // It is also properly aligned, because `u8` has an alignment of `1`. unsafe { - volatile_set((self as *mut Self).cast::(), 0, size_of::()); + volatile_set( + ptr::from_mut::(self).cast::(), + 0, + size_of::(), + ); } // Ensures self is overwritten with the `None` bit pattern. volatile_write can't be @@ -462,8 +465,8 @@ impl Zeroize for MaybeUninit { impl Zeroize for [MaybeUninit] { fn zeroize(&mut self) { let ptr = self.as_mut_ptr().cast::>(); - let size = self.len().checked_mul(size_of::()).unwrap(); - assert!(size <= isize::MAX as usize); + let size = self.len().checked_mul(size_of::()).expect("overflow"); + assert!(isize::try_from(size).is_ok()); // Safety: // @@ -489,7 +492,7 @@ where Z: DefaultIsZeroes, { fn zeroize(&mut self) { - assert!(self.len() <= isize::MAX as usize); + assert!(isize::try_from(self.len()).is_ok()); // Safety: // @@ -515,7 +518,7 @@ impl Zeroize for PhantomData { fn zeroize(&mut self) {} } -/// [`PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation. +/// [`PhantomData` is always zero sized so provide a `ZeroizeOnDrop` implementation. impl ZeroizeOnDrop for PhantomData {} macro_rules! impl_zeroize_tuple { @@ -726,7 +729,7 @@ where Z: Zeroize + ?Sized, { fn drop(&mut self) { - self.0.zeroize() + self.0.zeroize(); } } @@ -766,7 +769,7 @@ fn volatile_write(dst: &mut T, src: T) { /// Perform a volatile `memset` operation which fills a slice with a value /// -/// Safety: +/// # Safety /// The memory pointed to by `dst` must be a single allocated object that is valid for `count` /// contiguous elements of `T`. /// `count` must not be larger than an `isize`. @@ -846,7 +849,7 @@ pub unsafe fn zeroize_flat_type(data: *mut F) { // This is safe because `size_of()` returns the exact size of the object in memory, and // `data_ptr` points directly to the first byte of the data. unsafe { - volatile_set(data as *mut u8, 0, size); + volatile_set(data.cast::(), 0, size); } optimization_barrier(&data); } @@ -872,7 +875,7 @@ pub mod __internal { impl AssertZeroize for T { fn zeroize_or_on_drop(&mut self) { - self.zeroize() + self.zeroize(); } } } diff --git a/zeroize/tests/alloc.rs b/zeroize/tests/alloc.rs index 99df9518..de043330 100644 --- a/zeroize/tests/alloc.rs +++ b/zeroize/tests/alloc.rs @@ -1,5 +1,10 @@ -use std::alloc::{GlobalAlloc, Layout, System}; +#![allow( + missing_docs, + clippy::std_instead_of_core, + clippy::undocumented_unsafe_blocks +)] +use std::alloc::{GlobalAlloc, Layout, System}; use zeroize::Zeroize; // Allocator that ensures that deallocated data is zeroized. @@ -14,9 +19,7 @@ unsafe impl GlobalAlloc for ProxyAllocator { if layout.size() == 160 { for i in 0..layout.size() { let b = unsafe { core::ptr::read(ptr.add(i)) }; - if b != 0 { - panic!() - } + assert_eq!(b, 0); } } @@ -37,7 +40,7 @@ impl SecretBox { impl Drop for SecretBox { fn drop(&mut self) { - self.0.as_mut().zeroize() + self.0.as_mut().zeroize(); } } diff --git a/zeroize/tests/zeroize.rs b/zeroize/tests/zeroize.rs index f462a96f..33fdd155 100644 --- a/zeroize/tests/zeroize.rs +++ b/zeroize/tests/zeroize.rs @@ -1,5 +1,13 @@ //! zeroize integration tests. +#![allow( + clippy::missing_safety_doc, + clippy::std_instead_of_alloc, + clippy::std_instead_of_core, + clippy::undocumented_unsafe_blocks, + clippy::unwrap_used +)] + use std::{ marker::{PhantomData, PhantomPinned}, mem::{MaybeUninit, size_of}, @@ -56,7 +64,7 @@ fn zeroize_byte_arrays() { #[test] fn zeroize_on_drop_byte_arrays() { let mut arr = [ZeroizedOnDrop(42); 1]; - unsafe { core::ptr::drop_in_place(&mut arr) }; + unsafe { core::ptr::drop_in_place(&raw mut arr) }; assert_eq!(arr.as_ref(), [ZeroizedOnDrop(0); 1].as_ref()); } @@ -91,11 +99,11 @@ fn zeroize_check_tuple() { #[test] fn zeroize_on_drop_check_tuple() { let mut tup1 = (ZeroizedOnDrop(42),); - unsafe { core::ptr::drop_in_place(&mut tup1) }; + unsafe { core::ptr::drop_in_place(&raw mut tup1) }; assert_eq!(tup1, (ZeroizedOnDrop(0),)); let mut tup2 = (ZeroizedOnDrop(42), ZeroizedOnDrop(42)); - unsafe { core::ptr::drop_in_place(&mut tup2) }; + unsafe { core::ptr::drop_in_place(&raw mut tup2) }; assert_eq!(tup2, (ZeroizedOnDrop(0), ZeroizedOnDrop(0))); } @@ -121,9 +129,7 @@ fn zeroize_vec_entire_capacity() { impl Drop for PanicOnNonZeroDrop { fn drop(&mut self) { - if self.0 != 0 { - panic!("dropped non-zeroized data"); - } + assert!(self.0 == 0, "dropped non-zeroized data"); } } @@ -226,7 +232,7 @@ fn box_unsized_zeroizing() { } unsafe { - core::ptr::drop_in_place(&mut *b); + core::ptr::drop_in_place(&raw mut *b); } let s: &[u8] = &b; @@ -289,11 +295,11 @@ fn zeroizing_dyn_trait() { Box::new(Zeroizing::new(TestStruct { data: [1, 2, 3, 4] })); unsafe { - core::ptr::drop_in_place(&mut *b); + core::ptr::drop_in_place(&raw mut *b); } let inner: &Zeroizing = &b; - let inner: &dyn TestTrait = std::ops::Deref::deref(inner); + let inner: &dyn TestTrait = core::ops::Deref::deref(inner); assert_eq!(inner.data(), &[0, 0, 0, 0]); } diff --git a/zeroize/tests/zeroize_derive.rs b/zeroize/tests/zeroize_derive.rs index 2a2ab73b..58d8afeb 100644 --- a/zeroize/tests/zeroize_derive.rs +++ b/zeroize/tests/zeroize_derive.rs @@ -1,6 +1,7 @@ //! Integration tests for `zeroize_derive` proc macros #![cfg(feature = "zeroize_derive")] +#![allow(clippy::undocumented_unsafe_blocks)] use zeroize::{Zeroize, ZeroizeOnDrop}; @@ -11,7 +12,7 @@ fn derive_tuple_struct_test() { let mut value = Z([1, 2, 3]); value.zeroize(); - assert_eq!(&value.0, &[0, 0, 0]) + assert_eq!(&value.0, &[0, 0, 0]); } #[test] @@ -65,7 +66,7 @@ fn derive_struct_drop() { #[derive(Zeroize, ZeroizeOnDrop)] struct Z([u8; 3]); - assert!(std::mem::needs_drop::()); + assert!(core::mem::needs_drop::()); } /// Test that the custom macro actually derived `Drop` for `Z` @@ -78,7 +79,7 @@ fn derive_enum_drop() { Variant2(usize), } - assert!(std::mem::needs_drop::()); + assert!(core::mem::needs_drop::()); } /// Test that the custom macro actually derived `Drop` for `Z` @@ -87,7 +88,7 @@ fn derive_struct_only_drop() { #[derive(ZeroizeOnDrop)] struct Z([u8; 3]); - assert!(std::mem::needs_drop::()); + assert!(core::mem::needs_drop::()); } /// Test that the custom macro actually derived `Drop` for `Z` @@ -100,7 +101,7 @@ fn derive_enum_only_drop() { Variant2(usize), } - assert!(std::mem::needs_drop::()); + assert!(core::mem::needs_drop::()); } /// Test that `Drop` is not derived in the following case by defining a @@ -254,9 +255,9 @@ fn derive_inherit_zeroize_on_drop() { let mut value = Z(X([1, 2, 3])); unsafe { - std::ptr::drop_in_place(&mut value); + core::ptr::drop_in_place(&raw mut value); } - assert_eq!(&value.0.0, &[0, 0, 0]) + assert_eq!(&value.0.0, &[0, 0, 0]); } #[test] @@ -269,9 +270,9 @@ fn derive_inherit_from_both() { let mut value = Z(X([1, 2, 3])); unsafe { - std::ptr::drop_in_place(&mut value); + core::ptr::drop_in_place(&raw mut value); } - assert_eq!(&value.0.0, &[0, 0, 0]) + assert_eq!(&value.0.0, &[0, 0, 0]); } #[test] @@ -284,16 +285,16 @@ fn derive_inherit_both() { let mut value = Z(X([1, 2, 3])); unsafe { - std::ptr::drop_in_place(&mut value); + core::ptr::drop_in_place(&raw mut value); } - assert_eq!(&value.0.0, &[0, 0, 0]) + assert_eq!(&value.0.0, &[0, 0, 0]); } #[test] fn derive_deref() { struct X([u8; 3]); - impl std::ops::Deref for X { + impl core::ops::Deref for X { type Target = [u8]; fn deref(&self) -> &Self::Target { @@ -301,7 +302,7 @@ fn derive_deref() { } } - impl std::ops::DerefMut for X { + impl core::ops::DerefMut for X { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } @@ -312,9 +313,9 @@ fn derive_deref() { let mut value = Z(X([1, 2, 3])); unsafe { - std::ptr::drop_in_place(&mut value); + core::ptr::drop_in_place(&raw mut value); } - assert_eq!(&value.0.0, &[0, 0, 0]) + assert_eq!(&value.0.0, &[0, 0, 0]); } #[test] diff --git a/zeroize_derive/Cargo.toml b/zeroize_derive/Cargo.toml index b37f8a94..42f31582 100644 --- a/zeroize_derive/Cargo.toml +++ b/zeroize_derive/Cargo.toml @@ -20,5 +20,8 @@ proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full", "extra-traits", "visit"] } +[lints] +workspace = true + [package.metadata.docs.rs] rustdoc-args = ["--document-private-items"] diff --git a/zeroize_derive/src/lib.rs b/zeroize_derive/src/lib.rs index 98cc5618..65935cb1 100644 --- a/zeroize_derive/src/lib.rs +++ b/zeroize_derive/src/lib.rs @@ -304,12 +304,13 @@ impl ZeroizeAttrs { } } } else if meta.path().is_ident("skip") { - if variant.is_none() && binding.is_none() { - panic!(concat!( + assert!( + !(variant.is_none() && binding.is_none()), + concat!( "The #[zeroize(skip)] attribute is not allowed on a `struct` or `enum`. ", "Use it on a field or variant instead.", - )) - } + ) + ); } else { panic!("unknown #[zeroize] attribute type: {:?}", meta.path()); } @@ -332,9 +333,10 @@ fn generate_fields(input: &DeriveInput, method: TokenStream) -> TokenStream { .iter() .filter_map(|variant| { if attr_skip(&variant.attrs) { - if variant.fields.iter().any(|field| attr_skip(&field.attrs)) { - panic!("duplicate #[zeroize] skip flags") - } + assert!( + !variant.fields.iter().any(|field| attr_skip(&field.attrs)), + "duplicate #[zeroize] skip flags" + ); None } else { let variant_id = &variant.ident; @@ -421,6 +423,7 @@ fn impl_zeroize_on_drop(input: &DeriveInput) -> TokenStream { } #[cfg(test)] +#[allow(clippy::unwrap_used)] mod tests { use super::*; @@ -465,7 +468,7 @@ mod tests { } } }, - ) + ); } #[test] @@ -501,7 +504,7 @@ mod tests { } } }, - ) + ); } #[test] @@ -530,7 +533,7 @@ mod tests { } } }, - ) + ); } #[test] @@ -554,7 +557,7 @@ mod tests { } } }, - ) + ); } #[test] @@ -587,7 +590,7 @@ mod tests { #[doc(hidden)] impl ::zeroize::ZeroizeOnDrop for Z {} }, - ) + ); } #[test]