From a4567bebcf009c5cf9c9740b6bf4e0b0b6a3a000 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Fri, 24 Jan 2025 19:56:46 -0800 Subject: [PATCH] internals: Replace use of `as_rchunks` polyfill. Eliminate some uneeded `unsafe` code. --- src/limb.rs | 46 +++++++++++++++---------------------------- src/polyfill/slice.rs | 15 -------------- 2 files changed, 16 insertions(+), 45 deletions(-) diff --git a/src/limb.rs b/src/limb.rs index 7d95c2a031..fcda5c6b8a 100644 --- a/src/limb.rs +++ b/src/limb.rs @@ -21,9 +21,9 @@ use crate::{ c, constant_time, error::{self, LenMismatchError}, - polyfill::{slice, usize_from_u32, ArrayFlatMap}, + polyfill::{sliceutil, usize_from_u32, ArrayFlatMap}, }; -use core::num::NonZeroUsize; +use core::{iter, num::NonZeroUsize}; #[cfg(any(test, feature = "alloc"))] use crate::bits; @@ -201,37 +201,23 @@ pub fn parse_big_endian_and_pad_consttime( input: untrusted::Input, result: &mut [Limb], ) -> Result<(), error::Unspecified> { - let (partial, whole) = slice::as_rchunks(input.as_slice_less_safe()); - - let mut partial_padded: [u8; LIMB_BYTES]; - let partial_padded = match (partial, whole) { - (partial @ [_, ..], _) => { - partial_padded = [0; LIMB_BYTES]; - partial_padded[(LIMB_BYTES - partial.len())..].copy_from_slice(partial); - Some(partial_padded) - } - ([], [_, ..]) => None, - ([], []) => { - // Empty input is not allowed. - return Err(error::Unspecified); - } - }; - - let mut result = result.iter_mut(); - - for input in whole.iter().rev().chain(partial_padded.iter()) { - // The result isn't allowed to be shorter than the input. - match result.next() { - Some(r) => *r = Limb::from_be_bytes(*input), - None => return Err(error::Unspecified), - } + if input.is_empty() { + return Err(error::Unspecified); } - - // Pad the result. - for r in result { - *r = 0; + let input_limbs = input.as_slice_less_safe().rchunks(LIMB_BYTES).map(|chunk| { + let mut padded = [0; LIMB_BYTES]; + sliceutil::overwrite_at_start(&mut padded[(LIMB_BYTES - chunk.len())..], chunk); + Limb::from_be_bytes(padded) + }); + if input_limbs.len() > result.len() { + return Err(error::Unspecified); } + result + .iter_mut() + .zip(input_limbs.chain(iter::repeat(0))) + .for_each(|(r, i)| *r = i); + Ok(()) } diff --git a/src/polyfill/slice.rs b/src/polyfill/slice.rs index 52f24edf65..b585429c21 100644 --- a/src/polyfill/slice.rs +++ b/src/polyfill/slice.rs @@ -55,21 +55,6 @@ pub fn as_chunks_mut(slice: &mut [T]) -> (&mut [[T; N]], &mut (chunked, remainder) } -// TODO(MSRV feature(slice_as_chunks)): Use `slice::as_rchunks` instead. -// This is adapted from the above implementation of `as_chunks`. -#[inline(always)] -pub fn as_rchunks(slice: &[T]) -> (&[T], &[[T; N]]) { - assert!(N != 0, "chunk size must be non-zero"); - let len = slice.len() / N; - let (remainder, multiple_of_n) = slice.split_at(slice.len() - (len * N)); - // SAFETY: We already panicked for zero, and ensured by construction - // that the length of the subslice is a multiple of N. - // SAFETY: We cast a slice of `new_len * N` elements into - // a slice of `new_len` many `N` elements chunks. - let chunked = unsafe { core::slice::from_raw_parts(multiple_of_n.as_ptr().cast(), len) }; - (remainder, chunked) -} - // TODO(MSRV feature(slice_flatten)): Use `slice::flatten` instead. // This is derived from the libcore implementation, using only stable APIs. pub fn flatten(slice: &[[T; N]]) -> &[T] {