Version: 2.3.0 (also present on main)
Summary
Opening a SqlCipherKeyring via the passphrase path (no explicit key) hangs / OOMs. ConnectionParams::default().memory is initialized from get_default_memory_cost(), whose non-test definition returns a bytes value that is then used as Argon2's KiB m_cost.
#[cfg(test)]
fn get_default_memory_cost() -> u32 { Argon2Params::DEFAULT_M_COST } // 19456 (KiB) ✓
#[cfg(not(test))]
fn get_default_memory_cost() -> u32 { 19_917_824 } // "19456 KiB converted to bytes" ✗
derive_key passes params.memory straight into Argon2Params::new(memory, …), where m_cost is measured in KiB blocks. So the non-test default requests 19_917_824 KiB ≈ 19 GB, and the derivation stalls allocating/initializing that buffer.
Because the #[cfg(test)] variant returns the correct Argon2Params::DEFAULT_M_COST (19456), the crate's own test suite never exercises the broken value — only real (non-test) builds do.
Repro
use cryptex::sqlcipher::{ConnectionParams, SqlCipherKeyring};
let mut p = ConnectionParams::default();
p.password = b"pw".to_vec();
p.salt = b"saltsaltsaltsalt".to_vec();
// hangs on the ~19 GB Argon2 allocation:
let _ = SqlCipherKeyring::with_params(&p, Some(dir)).unwrap();
Setting p.memory = 19_456; (the correct KiB value) before the call makes it return in tens of milliseconds.
Also affected
- The
ConnectionParams doc example uses memory=19917824, propagating the bytes value.
- The
FromStr range check (Argon2Params::DEFAULT_M_COST..Argon2Params::MAX_M_COST) accepts the oversized value, so it isn't caught during parsing.
Suggested fix
- Make
#[cfg(not(test))] get_default_memory_cost() return Argon2Params::DEFAULT_M_COST (KiB), matching the test variant.
- Update the doc example to a KiB value.
- Optionally document that
ConnectionParams::memory is in KiB blocks, not bytes.
Version: 2.3.0 (also present on
main)Summary
Opening a
SqlCipherKeyringvia the passphrase path (no explicitkey) hangs / OOMs.ConnectionParams::default().memoryis initialized fromget_default_memory_cost(), whose non-test definition returns a bytes value that is then used as Argon2's KiBm_cost.derive_keypassesparams.memorystraight intoArgon2Params::new(memory, …), wherem_costis measured in KiB blocks. So the non-test default requests19_917_824 KiB ≈ 19 GB, and the derivation stalls allocating/initializing that buffer.Because the
#[cfg(test)]variant returns the correctArgon2Params::DEFAULT_M_COST(19456), the crate's own test suite never exercises the broken value — only real (non-test) builds do.Repro
Setting
p.memory = 19_456;(the correct KiB value) before the call makes it return in tens of milliseconds.Also affected
ConnectionParamsdoc example usesmemory=19917824, propagating the bytes value.FromStrrange check(Argon2Params::DEFAULT_M_COST..Argon2Params::MAX_M_COST)accepts the oversized value, so it isn't caught during parsing.Suggested fix
#[cfg(not(test))] get_default_memory_cost()returnArgon2Params::DEFAULT_M_COST(KiB), matching the test variant.ConnectionParams::memoryis in KiB blocks, not bytes.