From f434c9851da78d852e7debbcd65bec358eb651e2 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 17 Feb 2026 19:06:48 -0500 Subject: [PATCH] Avoid Vec allocation when parsing salt Pull elements directly from the split iterator instead of collecting into a Vec and using try_into. Co-Authored-By: Claude Opus 4.6 --- src/_bcrypt/src/lib.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/_bcrypt/src/lib.rs b/src/_bcrypt/src/lib.rs index ad38fdf..7cd1665 100644 --- a/src/_bcrypt/src/lib.rs +++ b/src/_bcrypt/src/lib.rs @@ -91,12 +91,14 @@ fn hashpw<'p>( // salt here is not just the salt bytes, but rather an encoded value // containing a version number, number of rounds, and the salt. // Should be [prefix, cost, hash]. This logic is copied from `bcrypt` - let [raw_version, raw_cost, remainder]: [&[u8]; 3] = salt - .split(|&b| b == b'$') - .filter(|s| !s.is_empty()) - .collect::>() - .try_into() - .map_err(|_| pyo3::exceptions::PyValueError::new_err("Invalid salt"))?; + let invalid_salt = || pyo3::exceptions::PyValueError::new_err("Invalid salt"); + let mut parts = salt.split(|&b| b == b'$').filter(|s| !s.is_empty()); + let raw_version = parts.next().ok_or_else(invalid_salt)?; + let raw_cost = parts.next().ok_or_else(invalid_salt)?; + let remainder = parts.next().ok_or_else(invalid_salt)?; + if parts.next().is_some() { + return Err(invalid_salt()); + } let version = match raw_version { b"2y" => bcrypt::Version::TwoY,