diff --git a/Cargo.lock b/Cargo.lock index 62844413d..cac350be8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,18 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "allocator-api2" version = "0.2.18" @@ -22,9 +10,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" @@ -32,17 +20,11 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "cc" -version = "1.1.21" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", @@ -68,12 +50,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.9" @@ -101,7 +89,6 @@ dependencies = [ "pcre2", "portable-atomic", "rand", - "rand_pcg", "rsconf", "serial_test", "terminfo", @@ -123,24 +110,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "getrandom" -version = "0.2.15" +name = "foldhash" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] [[package]] @@ -160,9 +149,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "lock_api" @@ -182,11 +171,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -234,9 +223,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "parking_lot" @@ -321,30 +310,21 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "portable-atomic" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -364,18 +344,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", "rand_core", ] @@ -384,24 +352,12 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_pcg" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" -dependencies = [ - "rand_core", -] [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags", ] @@ -441,7 +397,7 @@ checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -473,17 +429,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "terminfo" version = "0.9.0" @@ -502,18 +447,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "widestring" version = "1.1.0" @@ -592,24 +525,3 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] diff --git a/Cargo.toml b/Cargo.toml index fb9b76c0e..a2d559f3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,11 @@ nix = { version = "0.29.0", default-features = false, features = [ num-traits = "0.2.19" once_cell = "1.19.0" fish-printf = { path = "./printf", features = ["widestring"] } -rand = { version = "0.8.5", features = ["small_rng"] } + +# Don't use the "getrandom" feature as it requires "getentropy" which was not +# available on macOS < 10.12. We can enable "getrandom" when we raise the +# minimum supported version to 10.12. +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } widestring = "1.1.0" # We need 0.9.0 specifically for some crash fixes. terminfo = "0.9.0" @@ -56,7 +60,6 @@ portable-atomic = { version = "1", default-features = false, features = [ ] } [dev-dependencies] -rand_pcg = "0.3.1" serial_test = { version = "1.0.0", default-features = false } [build-dependencies] diff --git a/src/builtins/random.rs b/src/builtins/random.rs index 4ff31c236..f854aef62 100644 --- a/src/builtins/random.rs +++ b/src/builtins/random.rs @@ -1,12 +1,13 @@ use super::prelude::*; +use crate::util::get_rng; use crate::wutil; use once_cell::sync::Lazy; use rand::rngs::SmallRng; use rand::{Rng, SeedableRng}; use std::sync::Mutex; -static RNG: Lazy> = Lazy::new(|| Mutex::new(SmallRng::from_entropy())); +static RNG: Lazy> = Lazy::new(|| Mutex::new(get_rng())); pub fn random(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Option { let cmd = argv[0]; diff --git a/src/history.rs b/src/history.rs index 50ab39a27..1a22fd9d6 100644 --- a/src/history.rs +++ b/src/history.rs @@ -63,7 +63,7 @@ use crate::{ path_get_config, path_get_data, path_get_data_remoteness, path_is_valid, DirRemoteness, }, threads::{assert_is_background_thread, iothread_perform}, - util::find_subslice, + util::{find_subslice, get_rng}, wchar::prelude::*, wcstringutil::subsequence_in_string, wildcard::{wildcard_match, ANY_STRING}, @@ -956,7 +956,7 @@ impl HistoryImpl { let vacuum_frequency = 25; let countdown_to_vacuum = self .countdown_to_vacuum - .get_or_insert_with(|| rand::thread_rng().gen_range(0..vacuum_frequency)); + .get_or_insert_with(|| get_rng().gen_range(0..vacuum_frequency)); // Determine if we're going to vacuum. let mut vacuum = false; diff --git a/src/tests/history.rs b/src/tests/history.rs index 4de19092f..23c9622e8 100644 --- a/src/tests/history.rs +++ b/src/tests/history.rs @@ -4,9 +4,11 @@ use crate::history::{self, History, HistoryItem, HistorySearch, PathList, Search use crate::path::path_get_data; use crate::tests::prelude::*; use crate::tests::string_escape::ESCAPE_TEST_CHAR; +use crate::util::get_rng; use crate::wchar::prelude::*; use crate::wcstringutil::{string_prefixes_string, string_prefixes_string_case_insensitive}; -use rand::random; +use rand::rngs::SmallRng; +use rand::Rng; use std::collections::VecDeque; use std::ffi::CString; use std::io::BufReader; @@ -27,12 +29,12 @@ fn history_contains(history: &History, txt: &wstr) -> bool { false } -fn random_string() -> WString { +fn random_string(rng: &mut SmallRng) -> WString { let mut result = WString::new(); - let max = 1 + random::() % 32; + let max = rng.gen_range(1..=32); for _ in 0..max { - let c = char::from_u32(u32::try_from(1 + random::() % ESCAPE_TEST_CHAR).unwrap()) - .unwrap(); + let c = + char::from_u32(u32::try_from(1 + rng.gen_range(0..ESCAPE_TEST_CHAR)).unwrap()).unwrap(); result.push(c); } result @@ -154,6 +156,7 @@ fn test_history() { let mut after: VecDeque = VecDeque::new(); history.clear(); let max = 100; + let mut rng = get_rng(); for i in 1..=max { // Generate a value. let mut value = WString::from_str("test item ") + &i.to_wstring()[..]; @@ -164,10 +167,9 @@ fn test_history() { } // Generate some paths. - let mut paths = PathList::new(); - for _ in 0..random::() % 6 { - paths.push(random_string()); - } + let paths: PathList = (0..rng.gen_range(0..6)) + .map(|_| random_string(&mut rng)) + .collect(); // Record this item. let mut item = diff --git a/src/tests/string_escape.rs b/src/tests/string_escape.rs index 35fab6e8e..ba8ee7534 100644 --- a/src/tests/string_escape.rs +++ b/src/tests/string_escape.rs @@ -3,10 +3,10 @@ use crate::common::{ UnescapeStringStyle, ENCODE_DIRECT_BASE, ENCODE_DIRECT_END, }; use crate::locale::LOCALE_LOCK; +use crate::util::{get_rng_seed, get_seeded_rng}; use crate::wchar::{wstr, WString, L}; use crate::wutil::encoding::{wcrtomb, zero_mbstate, AT_LEAST_MB_LEN_MAX}; use rand::{Rng, RngCore}; -use rand_pcg::Pcg64Mcg; /// wcs2string is locale-dependent, so ensure we have a multibyte locale /// before using it in a test. @@ -102,7 +102,7 @@ fn test_escape_var() { fn escape_test(escape_style: EscapeStringStyle, unescape_style: UnescapeStringStyle) { setlocale(); let seed: u128 = 92348567983274852905629743984572; - let mut rng = Pcg64Mcg::new(seed); + let mut rng = get_seeded_rng(seed); let mut random_string = WString::new(); let mut escaped_string; @@ -175,10 +175,8 @@ fn str2hex(input: &[u8]) -> String { #[test] fn test_convert() { setlocale(); - use rand::random; - - let seed: u128 = random::(); - let mut rng = Pcg64Mcg::new(seed); + let seed = get_rng_seed(); + let mut rng = get_seeded_rng(seed); let mut origin = Vec::new(); for _ in 0..ESCAPE_TEST_COUNT { diff --git a/src/util.rs b/src/util.rs index ebef9a55f..e1093a486 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,10 @@ //! Generic utilities library. use crate::wchar::prelude::*; +use rand::{rngs::SmallRng, SeedableRng}; use std::cmp::Ordering; use std::time; +use std::time::{SystemTime, UNIX_EPOCH}; /// Compares two wide character strings with an (arguably) intuitive ordering. This function tries /// to order strings in a way which is intuitive to humans with regards to sorting strings @@ -170,6 +172,27 @@ pub fn get_time() -> i64 { } } +// Helper to get a small RNG seed, based on nanoseconds. +pub fn get_rng_seed() -> u128 { + // Note we use an explicit seed to avoid the "getrandom" crate, which uses `getentropy()` on macOS which + // is not available before macOS 10.12. + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos() +} + +// Helper to get a small RNG with a seed. +pub fn get_seeded_rng(seed: u128) -> SmallRng { + let seed = ((seed >> 64) as u64) ^ (seed as u64); + SmallRng::seed_from_u64(seed) +} + +// Helper to get a small RNG using the current time. +pub fn get_rng() -> SmallRng { + get_seeded_rng(get_rng_seed()) +} + // Compare the strings to see if they begin with an integer that can be compared and return the // result of that comparison. fn wcsfilecmp_leading_digits(a: &wstr, b: &wstr) -> (Ordering, usize, usize) { diff --git a/src/wutil/tests.rs b/src/wutil/tests.rs index 9ca1a3227..46723affb 100644 --- a/src/wutil/tests.rs +++ b/src/wutil/tests.rs @@ -1,7 +1,8 @@ use crate::fds::AutoCloseFd; use crate::tests::prelude::*; +use crate::util::get_rng; use libc::{c_void, O_CREAT, O_RDWR, O_TRUNC, SEEK_SET}; -use rand::random; +use rand::Rng; use std::{ffi::CString, ptr}; use crate::fallback::fish_mkstemp_cloexec; @@ -63,6 +64,7 @@ fn test_wwrite_to_fd() { let _cleanup = test_init(); let (_fd, filename) = fish_mkstemp_cloexec(CString::new("/tmp/fish_test_wwrite.XXXXXX").unwrap()).unwrap(); + let mut rng = get_rng(); let sizes = [1, 2, 3, 5, 13, 23, 64, 128, 255, 4096, 4096 * 2]; for &size in &sizes { let fd = AutoCloseFd::new(unsafe { @@ -71,7 +73,7 @@ fn test_wwrite_to_fd() { assert!(fd.is_valid()); let mut input = WString::new(); for _i in 0..size { - input.push(random()); + input.push(rng.gen()); } let amt = wwrite_to_fd(&input, fd.fd()).unwrap();