From eb4b8a44d3b5b52ef142345a89bf9eb6b3c77ec6 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 1 Jan 2021 14:34:38 +0000 Subject: [PATCH 1/2] Fix #1082 (seed_from_u64 with non multiple of 4) --- rand_core/CHANGELOG.md | 5 ++++- rand_core/src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index b502f9bc49e..c0c2418f9b2 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.6.1] - 2020-12-31 +## [0.6.1] - 2021-01-03 +### Fixed +- Avoid panic when using `RngCore::seed_from_u64` with a seed which is not a + multiple of four (#1082) ### Other - Enable all stable features in the playground (#1081) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index ff553a335ae..fdf82dd5e35 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -313,7 +313,7 @@ pub trait SeedableRng: Sized { let xorshifted = (((state >> 18) ^ state) >> 27) as u32; let rot = (state >> 59) as u32; let x = xorshifted.rotate_right(rot); - chunk.copy_from_slice(&x.to_le_bytes()); + chunk.copy_from_slice(&x.to_le_bytes()[..chunk.len()]); } Self::from_seed(seed) From 594aed829133a9df8219fd2a2670c631a03d5b19 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 2 Jan 2021 10:17:05 +0000 Subject: [PATCH 2/2] seed_from_u64: use newpavlov's suggestion --- rand_core/src/lib.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index fdf82dd5e35..7e847ae499a 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -300,20 +300,30 @@ pub trait SeedableRng: Sized { /// considered a value-breaking change. fn seed_from_u64(mut state: u64) -> Self { // We use PCG32 to generate a u32 sequence, and copy to the seed - const MUL: u64 = 6364136223846793005; - const INC: u64 = 11634580027462260723; + fn pcg32(state: &mut u64) -> [u8; 4] { + const MUL: u64 = 6364136223846793005; + const INC: u64 = 11634580027462260723; - let mut seed = Self::Seed::default(); - for chunk in seed.as_mut().chunks_mut(4) { // We advance the state first (to get away from the input value, // in case it has low Hamming Weight). - state = state.wrapping_mul(MUL).wrapping_add(INC); + *state = state.wrapping_mul(MUL).wrapping_add(INC); + let state = *state; // Use PCG output function with to_le to generate x: let xorshifted = (((state >> 18) ^ state) >> 27) as u32; let rot = (state >> 59) as u32; let x = xorshifted.rotate_right(rot); - chunk.copy_from_slice(&x.to_le_bytes()[..chunk.len()]); + x.to_le_bytes() + } + + let mut seed = Self::Seed::default(); + let mut iter = seed.as_mut().chunks_exact_mut(4); + for chunk in &mut iter { + chunk.copy_from_slice(&pcg32(&mut state)); + } + let rem = iter.into_remainder(); + if !rem.is_empty() { + rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]); } Self::from_seed(seed)