Skip to content

Commit 2bba6a1

Browse files
authored
argon2: add clippy lints to avoid panics (#334)
Expands the set of clippy lints applied to include ones intended to eliminate panics. Replaces `usize::try_from(n: u32).unwrap()` usages with `as u32` to avoid panics, avoiding possible truncation by adding a `compile_error!` if the `target_pointer_width` isn't 32 or 64-bit.
1 parent 0262c5a commit 2bba6a1

File tree

3 files changed

+43
-22
lines changed

3 files changed

+43
-22
lines changed

argon2/src/variable_hash.rs renamed to argon2/src/blake2b_long.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,25 @@ pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
1414
return Err(Error::OutputTooShort);
1515
}
1616

17-
let len_bytes = match u32::try_from(out.len()) {
18-
Ok(v) => v.to_le_bytes(),
19-
Err(_) => return Err(Error::OutputTooLong),
20-
};
17+
let len_bytes = u32::try_from(out.len())
18+
.map(|v| v.to_le_bytes())
19+
.map_err(|_| Error::OutputTooLong)?;
2120

2221
// Use blake2b directly if the output is small enough.
2322
if out.len() <= Blake2b512::output_size() {
24-
let mut digest = Blake2bVar::new(out.len()).unwrap();
23+
let mut digest = Blake2bVar::new(out.len()).map_err(|_| Error::OutputTooLong)?;
2524

2625
// Conflicting method name from `Digest` and `Update` traits
2726
digest::Update::update(&mut digest, &len_bytes);
27+
2828
for input in inputs {
2929
digest::Update::update(&mut digest, input);
3030
}
3131

3232
digest
3333
.finalize_variable(out)
34-
.expect("invalid Blake2bVar out length");
34+
.map_err(|_| Error::OutputTooLong)?;
35+
3536
return Ok(());
3637
}
3738

@@ -67,7 +68,7 @@ pub fn blake2b_long(inputs: &[&[u8]], out: &mut [u8]) -> Result<()> {
6768

6869
// Calculate the last block with VarBlake2b.
6970
let last_block_size = out.len() - counter;
70-
let mut digest = Blake2bVar::new(last_block_size).unwrap();
71+
let mut digest = Blake2bVar::new(last_block_size).map_err(|_| Error::OutputTooLong)?;
7172

7273
digest::Update::update(&mut digest, &last_output);
7374
digest

argon2/src/lib.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,22 @@
55
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
66
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
77
)]
8-
#![warn(rust_2018_idioms, missing_docs)]
8+
#![warn(
9+
clippy::cast_lossless,
10+
clippy::cast_possible_truncation,
11+
clippy::cast_possible_wrap,
12+
clippy::cast_precision_loss,
13+
clippy::cast_sign_loss,
14+
clippy::checked_conversions,
15+
clippy::implicit_saturating_sub,
16+
clippy::panic,
17+
clippy::panic_in_result_fn,
18+
clippy::unwrap_used,
19+
missing_docs,
20+
rust_2018_idioms,
21+
unused_lifetimes,
22+
unused_qualifications
23+
)]
924

1025
//! ## Usage (simple with default params)
1126
//!
@@ -55,6 +70,11 @@
5570
//! # }
5671
//! ```
5772
73+
// Call sites which cast `u32` to `usize` and are annotated with
74+
// allow(clippy::cast_possible_truncation) need this check to avoid truncation.
75+
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
76+
compile_error!("this crate builds on 32-bit and 64-bit platforms only");
77+
5878
#[cfg(feature = "alloc")]
5979
#[macro_use]
6080
extern crate alloc;
@@ -63,10 +83,10 @@ extern crate alloc;
6383
extern crate std;
6484

6585
mod algorithm;
86+
mod blake2b_long;
6687
mod block;
6788
mod error;
6889
mod params;
69-
mod variable_hash;
7090
mod version;
7191

7292
pub use crate::{
@@ -84,11 +104,8 @@ pub use {
84104
password_hash::{self, PasswordHash, PasswordHasher, PasswordVerifier},
85105
};
86106

87-
use crate::variable_hash::blake2b_long;
88-
use blake2::{
89-
digest::{self, Output},
90-
Blake2b512, Digest,
91-
};
107+
use crate::blake2b_long::blake2b_long;
108+
use blake2::{digest, Blake2b512, Digest};
92109

93110
#[cfg(all(feature = "alloc", feature = "password-hash"))]
94111
use password_hash::{Decimal, Ident, ParamsString, Salt};
@@ -236,7 +253,7 @@ impl<'key> Argon2<'key> {
236253
self.fill_blocks(memory_blocks.as_mut(), initial_hash)
237254
}
238255

239-
#[allow(unused_mut)]
256+
#[allow(clippy::cast_possible_truncation, unused_mut)]
240257
fn fill_blocks(
241258
&self,
242259
memory_blocks: &mut [Block],
@@ -248,23 +265,23 @@ impl<'key> Argon2<'key> {
248265
.ok_or(Error::MemoryTooLittle)?;
249266

250267
let segment_length = self.params.segment_length();
251-
let iterations = usize::try_from(self.params.t_cost()).unwrap();
268+
let iterations = self.params.t_cost() as usize;
252269
let lane_length = self.params.lane_length();
253270
let lanes = self.params.lanes();
254271

255272
// Initialize the first two blocks in each lane
256273
for (l, lane) in memory_blocks.chunks_exact_mut(lane_length).enumerate() {
257274
for (i, block) in lane[..2].iter_mut().enumerate() {
258-
let i = u32::try_from(i).unwrap();
259-
let l = u32::try_from(l).unwrap();
275+
let i = i as u32;
276+
let l = l as u32;
260277

261278
let inputs = &[
262279
initial_hash.as_ref(),
263280
&i.to_le_bytes()[..],
264281
&l.to_le_bytes()[..],
265282
];
266283

267-
blake2b_long(inputs, block.as_mut_bytes()).unwrap();
284+
blake2b_long(inputs, block.as_mut_bytes())?;
268285
}
269286
}
270287

@@ -440,7 +457,8 @@ impl<'key> Argon2<'key> {
440457
}
441458

442459
/// Hashes all the inputs into `blockhash[PREHASH_DIGEST_LEN]`.
443-
fn initial_hash(&self, pwd: &[u8], salt: &[u8], out: &[u8]) -> Output<Blake2b512> {
460+
#[allow(clippy::cast_possible_truncation)]
461+
fn initial_hash(&self, pwd: &[u8], salt: &[u8], out: &[u8]) -> digest::Output<Blake2b512> {
444462
let mut digest = Blake2b512::new();
445463
digest.update(&self.params.p_cost().to_le_bytes());
446464
digest.update(&(out.len() as u32).to_le_bytes());

argon2/src/params.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl Params {
4242
pub const DEFAULT_M_COST: u32 = 4096;
4343

4444
/// Minimum number of memory blocks.
45+
#[allow(clippy::cast_possible_truncation)]
4546
pub const MIN_M_COST: u32 = 2 * SYNC_POINTS as u32; // 2 blocks per slice
4647

4748
/// Maximum number of memory blocks.
@@ -146,8 +147,9 @@ impl Params {
146147
}
147148

148149
/// Get the number of lanes.
150+
#[allow(clippy::cast_possible_truncation)]
149151
pub(crate) fn lanes(&self) -> usize {
150-
usize::try_from(self.p_cost).unwrap()
152+
self.p_cost as usize
151153
}
152154

153155
/// Get the number of blocks in a lane.
@@ -159,7 +161,7 @@ impl Params {
159161
///
160162
/// Minimum memory_blocks = 8*`L` blocks, where `L` is the number of lanes.
161163
pub(crate) fn segment_length(&self) -> usize {
162-
let m_cost = usize::try_from(self.m_cost).unwrap();
164+
let m_cost = self.m_cost as usize;
163165

164166
let memory_blocks = if m_cost < 2 * SYNC_POINTS * self.lanes() {
165167
2 * SYNC_POINTS * self.lanes()

0 commit comments

Comments
 (0)